Documentation Menu Close Menu

Datica CKS Documentation

Getting started

What is CKS?

Everyone is excited about Kubernetes, including us! Datica is proud to offer a secure, compliant Kubernetes managed service we’re calling CKS.

CKS stands for “Compliant Kubernetes Service”. CKS is a managed Kubernetes service — a service that can be defined in a number of different ways. At a foundational level, a managed Kubernetes service assumes management of the control plane, a group of controllers that take care of routine tasks to ensure the desired state of the cluster matches the observed state. Because Kubernetes can be configured and deployed in a number of different ways, users are often confused about how to setup and manage a Kubernetes cluster.

It is because of this problem that managed Kubernetes service providers exist. The biggest players in this space are the three large cloud providers, Google Cloud Platform, Amazon Web Services, and Microsoft Azure. As Kubernetes adoption increases, so too is the need for a secure, compliant version of Kubernetes.

Although many of the existing managed Kubernetes services offer HIPAA eligibility, that doesn’t necessarily make them compliant, at least not out of the box. In order to ensure a cluster is defensibly compliant, a user would have to develop a clear definition of everything the product does to ensure compliance (in a signed legal agreement) as well as have a BAA in place with the service provider. The only other option is for the user to be responsible for the configuration of the underlying cluster, the operating system that runs the cluster and the instances (servers) the operating systems lives on.

The big cloud providers will provide sufficient descriptions of their product and possibly even sign a BAA, but gaps remain. Configuring logging, monitoring, intrusion detection, networking, an operating system, as well as a whole slew of infrastructure level configurations defeats the purpose of a managed service — the primary benefit of which is that a customer doesn’t have to worry about the aforementioned components or their intended configurations.

If you’re working within a regulated industry like healthcare you have very few options when it comes to using Kubernetes — either you manage the Kubernetes control plane, the operating system and the underlying infrastructure to maintain the flexibility required for compliance, or you risk falling out of compliance by using a managed service (because they don’t provide the configuration flexibility to achieve compliance). Datica is changing this.

This is where CKS comes in. In addition to managing the control plane, Datica also configures the underlying operating system (and manages it in perpetuity), configures the underlying instances — and installs, configures and manages a set of deployments required for compliance. These deployments include logging, monitoring, intrusion detection, vulnerability scanning and antivirus software.

In addition to the technical configuration, Datica assumes the liability for the complete stack in our BAA, something not available or possible with any other managed Kubernetes offering. CKS delivers a compliant managed Kubernetes service that functions like any other Kubernetes cluster, but one that comes pre-configured for compliance out of the box.

CKS architecture

CKS Architecture Overview

In this section we’ll review the CKS architecture and the various components outside of a user’s cluster that help Datica maintain compliance and security. Below we cover each component from the diagram above.

Cloud accounts

CKS_Architecture_Accounts

The two largest boxes in the diagram include both Datica’s Cloud Account and Customer’s Cloud Account labels. These correspond to each parties existing cloud account and are intended to represent separate entities (Datica and a third party).

clusters

Inside the cloud account boxes there are two darker boxes that correspond to Kubernetes clusters. The one in Datica’s Cloud Account is called the Lighthouse Cluster and the one in the customer’s cloud account is called CKS. We name these clusters differently so it’s easier to discuss throughout this guide, but in reality the Lighthouse Cluster is a CKS cluster itself.

The Lighthouse Cluster is a centrally managed CKS cluster that provides Datica with a number of different tools to help manage compliance. Those include:

  • Core API: Datica’s authentication system that manages organizations, users, groups and ACLs;
  • Syndication: The command center for managing all CKS clusters including making software updates and receiving compliance state information;
  • Vault: Datica’s public key infrastructure responsible for managing encryption across all CKS clusters;
  • Compliance engine: Responsible for serving the Cloud Compliance Management System, including continuous compliance checks against the cluster’s running state;

Secure connection

CKS_Architecture_Connection

In between the two clusters is a box representing the secure TLS connection between the Lighthouse and every customer cluster managed by Datica. This connection is required to receive real-time compliance information from each CKS cluster. The Lighthouse processes this information and feeds that back into our compliance model to determine if a customer’s cluster is compliant or not.

Inside a CKS Cluster

CKS_Architecture_CKS

A standard CKS cluster is comprised of three controllers and three workers. Datica configures the cluster for high availability to avoid a single point of failure. The compliance deployments — logging, monitoring, intrusion detection, networking, and vulnerability scanning, consuming roughly 8GB of memory on a single worker. However, some of these pods only need to live on a single worker.

Customers will have roughly 40GB of additional memory to allocate to their workloads. Of course, a CKS cluster can handle almost an unlimited number of workers.

More information

Below is a brief slide deck on CKS. These slides go over why we built a Kubernetes offering and the support and services associated with this new product. In addition, they give an overview of the Datica managed deployments and the shared responsibility model (what you do vs. what we do). This slide deck is not intended to replace the rest of the getting started guide, rather to reinforce the concepts we’ll discuss later on.

If you have questions while viewing the slides please read on throughout the rest of the guide as they will likely be answered in later sections.

To better understand CKS, it will help to briefly review Datica’s Legacy Platform product. In the world of cloud computing there are a number of different paths that lead to running and managing workloads. Whether you’re building a complex data processing application that performs sentiment analysis, or you’re a startup with a basic monolithic application that helps doctor offices schedule better — you will at some point make a decision around how you’re going to manage these pieces of software (and likely several times over throughout the course of their life cycles).

The path of least resistance to the cloud has traditionally involved utilizing a Platform as a Service (PaaS). A PaaS allows users to focus on application development, rather than the repetitive, lower-level tasks of managing workloads on a server. We’ve written extensively about PaaS offerings and encourage users to read through these articles.

In 2014 when Datica built it’s first product we did so with the assumption that PaaS was the future of application development and management in the cloud. While that turned out to be true to a certain extent, concepts like containerization and projects like Kubernetes have disrupted that thinking. Software has become too complex for PaaS. Organizations are growing and their use cases require more flexibility. As a result of this shift, Datica embarked on creating a compliant Kubernetes offering in late 2017.

Our goals for CKS were straight forward:

  • (For application developers) ensure CKS functions just as any other Kubernetes cluster.
  • Have no vendor lock-in, offer CKS as a cross-cloud solution.
  • Map Kubernetes controls to HITRUST and fill in the gaps with managed deployments.
  • Ensure all CKS clusters are continuously compliant through real-time configuration monitoring.

From December 2017 to May 2018 this is what we focused on building. CKS officially went generally available on June 1. Since then we’ve been accepting new customers as well as helping current Legacy PaaS customers migrate.

In our list of goals, we’ve achieved the following so far:

Functionality: CKS functions just as any other Kubernetes cluster. 95% of what Datica adds in terms of compliance and security happens behind the scenes.

Architecture: We’ve architected CKS to avoid vendor lock-in. We currently work with AWS and we look forward to supporting other cloud service providers in the future.

HITRUST: We’ve mapped HITRUST controls to Kubernetes functionality and configuration while providing additional tooling for logging, monitoring, intrusion detection, vulnerability scanning and more as Datica managed deployments.

Continuous Compliance: We’ve also completed writing a set of verification checks that continuously monitor the running state of each cluster. This work will provide us with a base to build better visibility into the security and compliance of the system. This visibility will be released as a new product — Datica’s Cloud Compliance Management System (CCMS). The CCMS will function as a compliance dashboard for CKS clusters. We currently do not have a timeline for the CCMS dashboard. However, major backend functionality is in progress.

CKS vs. others

As you explore the CKS product, you may be wondering how it is differentiated from other Kubernetes managed services like Amazon Elastic Container Service for Kubernetes (EKS) or Google’s Kubernetes Engine (GKE). One of the common points of confusion we see when talking to users is compliance eligibility vs. compliance provability. Eligibility simply means that the underlying CSP will sign a BAA — a document outlining how PHI will be stored, transmitted and accessed. The end user is still responsible for making the service compliant through proper logging, monitoring, configuration and more.

CKS on the other hand comes pre-configured with logging, monitoring, intrusion detection, volume backups, network encryption and a managed OS, among other things. With CKS, users no longer have to configure or manage their cluster for compliance.

Where CKS fits

If you’re new to Datica, CKS will be home to all applications that store or transmit sensitive information, like PII or PHI. Because Datica is aligned with HITRUST, customers can take advantage of global deployments and rest easy knowing they’re covered for localized compliance regimes like GDPR, IRAP and more. We’re also constantly adding support for new compliance frameworks, for more information see our compliance roadmap here.

We’re hopeful about the future of Kubernetes and cloud native applications. Our efforts to build CKS align with demand from our customers to allow for more flexibility within Datica’s product offering. As an organization we are committed to helping the cloud native community grow through adoption and a commitment to open source software.

If you have any questions, comments or feedback about our shift to CKS, please email us directly at product@datica.com.

Expectations

Throughout the rest of the getting started guide we’ll walk you through:

  • How to learn Kubernetes with a curated list of resources
  • How to request a CKS cluster
  • How to access your new cluster
  • How to access Datica managed deployments
  • Understanding the shared responsibility model

CKS versioning policy

Datica addresses vulnerabilities and security issues as they become publicly available. Kubernetes upgrades and deployment tooling updates happen on a quarterly basis (unless a security liability is present, in which case we would update as soon as possible). Below is a list of the current versions of software we run:

  • CoreOS: 1688.5.3
  • Kubernetes: 1.11.5
  • etcd: 3.2.18
  • Prometheus: 2.2.0
  • Elasticsearch: 6.1.2
  • FluentD: 1.0.2
  • Kibana: 6.1.2
  • Grafana: 5.0.0
  • ClamAV: 0.100.1
  • CRI-O: 1.11.3
  • Flannel: 0.10.0
  • Nginx Ingress Controller: 0.14.0
  • CoreDNS: 1.0.6

Learning resources

Already familiar with Kubernetes? Feel free to skip this section and jump right to Basic Prerequisites

Preparing for Kubernetes can seem daunting on the surface. Luckily Datica takes care of the hard parts for you. The biggest effort to end users is figuring out what their deployments look like on Kubernetes. Tactically what that means is you’ll need to figure out logical groupings of containers, services, and other components of your application.

While Kubernetes can essentially work however you’d like, and since you can containerize pretty much anything, the lift from a non-Kubernetes deployment model to a Kubernetes-ready deployment model can be fairly light. However, if you’re re-architecting, and moving toward a cloud native model — containerized workloads with micro-services automatically orchestrated by Kubernetes, it can be somewhat involved.

The good news is that Kubernetes and containerization has drastically increased in popularity over the last year. The number of resources online are growing daily. This article is intended to give you quality, recommended resources as a starting point for your Kubernetes journey. Each set of resources is broken down by category below.

Containerization

Article: Principles of Container-based Application Design - in this article, Bilgin Ibryam discusses the seven principles of container-based application design and how you can integrate those into your development process.

White-paper: Principles of Container-based Application Design - this is the accompanying white-paper to the article above. This paper goes into more detail on the seven principles.

Article: Developing on Kubernetes - in this article, Michael Hausenblas and Ilya Dmitrichenko discuss approaching Kubernetes development as a software developer. The authors walk you through various CI/CD tools and approaches, with several hands on examples that you can try. This is a great article for those looking for a better understanding of how cloud native applications are deployed and kept up to date.

Working with Kubernetes

Once you’ve containerized your application and or made the necessary architectural changes, the next step is to start working with Kubernetes directly. The very first step in that process is getting a cluster stood up:

  • The simple way: By far the easiest way to get a working cluster up is by install minikube locally on your machine. Minikube is a single-node Kubernetes cluster that requires almost no configuration and is the path of least resistance to start using Kubernetes.
  • The hard way: If you’re looking to really learn how Kubernetes works, this guide is one of the best resources available. It goes into intricate detail on getting a cluster stood up and configured.

Note: Both options above are for getting a handle on Kubernetes, not getting a compliant Kubernetes cluster up and running. Once you’re ready for production, you will work with Datica to get a compliant cluster stood up. The above recommendations are for local testing purposes only.

After you’ve got a cluster stood up using one of the three options above, the next step is start deploying and playing around with the Kubernetes internals. By far the most important step in this process is figuring out how to map your architecture to the various concepts within Kubernetes. Those important concepts include:

Deployments

Deployments help users manage replicated pods by allowing for easy modification of configuration. Having control over this configuration allows for Kubernetes to manage updates between application versions, and maintenance of historical events.

More information on Deployments »

Pods

Pods are the smallest unit of scheduling in the world of Kubernetes. Pods typically contain a number of tightly coupled containers. These containers typically share a common network or perhaps a specific configuration. Pods are almost always created via Deployments in Kubernetes.

More information on Pods »

StatefulSets

StatefulSets are specialized pod controllers that allow for better control over stable and unique network identifiers, persistent storage, graceful deployments and scaling. The primary use case for StatefulSets is in managing databases and persistent storage objects within Kubernetes.

More information on StatefulSets »

DaemonSets

Like StatefulSets, DaemonSets are specialized pod controllers that allow for an instance of a pod to run on a set of specified nodes. Datica uses DaemonSets for managing logging, monitoring and other compliance related tooling.

More information on DaemonSets »

Other Resources

Basic prerequisites

Once you’ve established contact with Datica, the first step is to work with our sales department on understanding your organization’s needs as they pertain to compliance and security in the cloud. This will likely require a few in depth discussions as well as a technical overview of CKS.

From there, we’ll put together a contract based on these conversations. Once the contract is signed by both parties, Datica will schedule the provisioning of your new CKS cluster. Because CKS is still a new offering, we require 3-5 days of lead time. Once you’re in the queue, our services team will establish contact with your organization and securely request the following information:

  • Legal business name (used for certificate generation)
  • What you’d like to name your cluster (ex: “Staging01”)
  • Initial user administrators (a list of emails)
  • Your cloud provider account ID
  • Your cloud provider access key
  • Your cloud provider secret key
  • Which region you’d like to deploy the cluster
  • Which region you’d like for data replication
  • Which region you’d like for S3 replication
  • S3 bucket name
  • A name for you cluster key (ex: “staging01-key”)
  • An ssh public key file
  • Which instances type/size for your nodes (we currently do not support odd instances)

Note: This account should be created within the “Datica” group. This will ensure any additional services are accessible to us. In addition to the information above, we’ll also need root access for the time being.

Once you’ve collected the above information and you’ve set the proper permissions, we’ll then need to know:

  • How many controller nodes you require (we require a minimum of 3 controllers to ensure HA, you may choose to have more)
  • How many workers you require (we deploy 3 by default)
  • Which node type/size for your controllers and workers (we currently do not support odd instances and have a minimum requirement of m4.xlarge)

All of this information will be collected via a secure form that we share with you. We do not expect our users to be Kubernetes configuration experts. As a result, a number of concepts may be unfamiliar to you. Not to worry, the Datica services team will be more than happy to walk you through how to properly size and configure your cluster.

Access

Once we’ve provisioned your new cluster, we’ll grant you access to that cluster. That process is as follows:

We’ll create an organization on your behalf using the legal business name collected above. This organization lives within Datica’s centralized authentication system. This system is responsible for managing users and cluster access. After we’ve created the organization, you’ll be sent an invite to your email on file (as well as any other administrators). Use this email to activate your account.

Once you’ve activated your account, you’ll need to download and install the Datica datikube CLI utility. You can download the package and view instructions for installation here.

Once you’ve installed datikube, you’ll need three pieces of information:

  • NAME - This is the name you’d like to use for your cluster (ex: “prod”, “staging”, etc.). Datica will configure this for you.
  • CLUSTER-URL- This is a URL at which this cluster’s kube-apiserver is accessible. Datica will provide this to you.
  • CA-FILE - This should be the relative path to the CA cert for this cluster. Datica will provide you with this file.

After you’ve gathered your cluster’s name, cluster-url, and the ca-file, you can run the following command:

datikube set-context <NAME> <CLUSTER-URL> <CA-FILE>

Ex: datikube set-context prod-cluster https://192.168.99.100:8443 ~/.example/ca.crt

After successfully running the datikube set-context command with the parameters above, you can begin using your new compliant cluster!

Before deploying your workloads onto your new Kubernetes cluster. You’ll want to ensure you can access the various deployments Datica provides. Those include:

  • Logging access: kubectl port-forward -n logging service/kibana 8001:5601 - In your browser, the kibana dashboard can be accessed at the following url: http://localhost:8001
  • Monitoring access: kubectl port-forward -n monitoring service/grafana 8002:3000 - In your browser, the grafana dashboard can be accessed at the following url: http://localhost:8002

IMPORTANT You should always make an effort to use kubectl authenticated with your Datica account credentials. However, sometimes you may want or need to use tools that require system roles. These types of tools cannot make use of Datica’s webhook authentication/authorization. You must make use of Kubernetes RBAC functionality. Since this is in your application space, you will be responsible for proving and ensuring the security and compliance of the roles you set up in accordance with your own company policies.

Groups and ACLs

Kubernetes ACLs can be constructed using the following sections, separated by:

  • product - The first part of the ACL string should always be the exact string “product”.
  • cluster - The second part of the ACL string should always be the exact string “cluster”.
  • cluster name - The name of the cluster you want the ACL to apply to.
  • action - This part of the ACL string should always be the exact string “action” OR “*”.
  • group - A group is a kubernetes-specific concept that overlaps with Datica’s groups. With Datica CKS, this should always be *.
  • namespace - A namespace is a kubernetes-specific concept. You can learn more about namespaces here.
  • resource - A resource is a Kubernetes-specific concept and is essentially any object that is set up on Kubernetes. You can see the full list of Kubernetes resource types here.
  • verb - The last part of the ACL string is the HTTP verb. The list of possible verbs can be viewed here. Make sure to use the request verbs, not the HTTP verbs. Case matters, so get will work as a verb, but GET will not. A final note on verbs: the kubectl port-forward command requires the ability to create pods. When completely assembled, the string should look something like product:cluster:[cluster-name]:action:*:[namespace]:[resource]:[verb]

ACL String Examples: To give a group access to retrieve the pods from a specific namespace, use the following ACL string: product:cluster:mycluster:action:*:examplenamespace:pods:list. This ACL string will provide users in this group access to list pods in the “examplenamespace” namespace using kubectl like kubectl -n examplenamespace get pods.

To give a group access to view monitoring, use the following ACL string: product:cluster:mycluster:action:*:monitoring:*. This ACL string will provide users in this group access to retrieve all resources that are in the “monitoring” namespace.

To give a group access to view logging, use the following ACL string: product:cluster:mycluster:action:*:logging:*. This ACL string will provide users in this group access to retrieve all resources that are in the “logging” namespace.

To give a group full access to a specific namespace, use an ACL string like this: product:cluster:mycluster:action:*:examplenamespace:*:*. This ACL string will provide users in the group complete access to the “examplenamespace” namespace.

Limiting Application Access

Developers may come across use cases in which an application will require talking to another component within CKS. For example, a CI/CD pipeline using Jenkins or Gitlab that deploys directly into a cluster will require interacting with the API server. In these cases, you should create a dedicated serviceaccount with permissions limited to only what your application requires.

Note: The Jenkins tutorial linked above makes use of minikube. Be aware that some commands will differ from CKS.

The general steps (taken from the article linked above) for using a serviceaccount to provide limited permissions to an application are as follows:

  1. Create namespace: kubectl create ns myapp
  2. Create a serviceaccount: kubectl -n myapp create sa thesa
  3. Create a rolebinding: kubectl -n myapp create rolebinding samplerolebinding --clusterrole=edit --serviceaccount=myapp:thesa
  4. Deploy the application: kubectl -n myapp run theapp --image=quay.io/whatever/theapp:0.42 --serviceaccount=thesa

For more information about default and user-facing roles available for use with RBAC, see the Kubernetes documentation.

Networking

Ingress

In order to allow your users and the public to reach your site, you should use the ingress (a collection of rules that allow inbound connections to reach your services) that Datica provides. This is important to help ensure that all traffic is encrypted.

The ingress maps a hostname and path (which could just be / to route all traffic from the hostname) to a kubernetes service. For each cluster there is a single ingress-controller which has a public ELB. As an end-user, you can create a CNAME record that maps whatever domain name you’d like to the ELB’s DNS name. You would then use that CNAME as the hostname in the ingress resource for your application. What this does is tell the ingress-controller that any traffic sent to the CNAME should be directed to the service that is specified in the ingress.

Other configurations

It is important to note that when creating resources on Kubernetes, it is imperative to always use Datica-provided networking solutions. In particular, do not use the host network for resources (such as the setting hostNetwork: true) as this can result in unencrypted traffic. ALWAYS use Datica’s provided ingress.

Tutorials

Kubernetes Dashboard

Note: In order to install an application that requires system roles or service accounts on Datica CKS, it’s necessary to first install the application using the Datica RBAC Admin user and then configure the roles for use using Datikube authentication. In the case of kubernetes-dashboard, the project recommends the creation of a system role and associated policies to limit the privileges granted to the application. Refer to the Kubernetes Dashboard documentation for more information about what privileges are set up.

Installing the Kubernetes Dashboard using the RBAC Admin certificate

To install the Kubernetes Dashboard application in your cluster, execute the following commands (Before beginning this step, set a kubectl context that uses the Admin certificate):

kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/master/src/deploy/recommended/kubernetes-dashboard.yaml

Accessing the Dashboard

To help ensure that all access to the Dashboard and resources running on Kubernetes is handled appropriately, authenticate against the Kubernetes Dashboard using your Datica account. This prevents you from having to manage system roles directly and from accidentally exposing your cluster to would-be attackers due to misconfiguration. All access control is handled via Datica Groups and ACLs.

Step 1

Make sure you have an up-to-date Datica session token for use later on — then run $ datikube refresh and enter your account credentials when prompted. Next you can retrieve your updated token by running (save this token for use in step 4):

$ echo `kubectl config view -o jsonpath='{.users[?(@.name == "datica")].user.token}'`

Step 2

Next we’re going to get the running pod name for the dashboard by running:

$ kubectl -n kube-system get pods | grep kubernetes-dashboard

This will output something similar to the following line:

kubernetes-dashboard-5bd6f767c7-44446                                   1/1       Running            0          25m

The first part is the pod name that is needed for the next step.

Step 3

In this step we’re going to set up port-forward to the dashboard using the kubernetes-dashboard pod name. This allows you to securely access the dashboard through https://localhost:8001/. Run:

$ kubectl -n kube-system port-forward <pod-name> 8001:8443

(replace with the name of the pod running your dashboard (e.g. kubernetes-dashboard-5bd6f767c7-44446)

Now you can navigate to https://localhost:8001

Note: Unless you replaced it during installation, your browser will report the certificate as invalid because the kubernetes-dashboard serves self-signed certificates by default, which is specified in the kubernetes-dashboard.yaml deployment file. The kubernetes-dashboard documentation provides instructions for replacing these certificates with valid CA-signed certificates. IMPORTANT: Whether you use self-signed or CA-signed certificates, Datica strongly recommends that you do not expose your kubernetes dashboard to the public Internet.

Step 4

The last step is to authenticate using Datica session token. At the login screen, select “Token” and enter the token from step 2. At this point, you should be able to see and use the kubernetes dashboard per its documentation. Remember, your permissions in the dashboard will be limited by the ACLs you have access to via Datica’s Product Dashboard.

Private VPN Connections

In this document we will demonstrate how to connect a remote application to your application running in your Kubernetes cluster. For the demonstration we will be using the AWS VPC VPN, an internal-only Ingress service, and the Kubernetes Guestbook example application. This document makes no assumptions about the VPN device being connected to other than familiarity with the device and ipsec VPN that supports IKEv1. One of the reason we are performing this demonstration using the AWS VPC VPN is that at the end of the VPN setup process you can download a configuration for a number of common VPN devices.

To get started we will need to gather some information about the VPN device to which we are connecting. The following information will be needed:

  • Internet IP address of the VPN device
  • If you plan on using Border Gateway Protocol for dynamic routing you will need the BGP ASN of the VPN device
  • If you plan on using static routing you will need CIDR ranges associated with the remote network(s)

Once you have this information you can proceed with the creation of the VPN following the instructions from AWS (https://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/SetUpVPNConnections.html). One important thing to note about the AWS VPN is that it does not act as a connection initiator. If you plan on initiating connections from your application running on Kubernetes, you will need to set up some sort of ping or keepalive on the remote side to keep the VPN up.

Now that you have a working VPN connection you can expose the application to the VPC. This is accomplished using a Kubernetes Ingress service with a load balancer set to internal-only mode. To get an application working for demonstration purposes I used the Guestbook application provided by Kubernetes (https://kubernetes.io/docs/tutorials/stateless-application/guestbook/). I followed this example pretty closely. The only changes I made were to install the application into its own namespace so that it would be easier to completely remove, and also the changes needed for it to utilize an internal-only Ingress service. In the frontend-service.yaml file I changed type: NodePort to type: ClusterIP. I then created an ingress configuration for the service which is as follows:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: frontend-ingress
  annotations:
    kubernetes.io/ingress.class: internal-nginx
  namespace: guestbook
spec:
  tls:
    - hosts:
      - guestbook.mycluster.example.com
      secretName: guestbook-certificate
  rules:
    - host: guestbook.mycluster.example.com
      http:
        paths:
        - path: /
          backend:
            serviceName: frontend
            servicePort: 80

Of particular importance is the kubernetes.io/ingress.class annotation. This is what assigns this ingress to the internal ingress service. Since the ingress service is configured to only allow https, I also needed to create a certificate and put it in a secret. You can see that the above ingress config specifies some tls settings. This tells the internal ingress service that this ingress needs to use the certificate located in the the guestbook-certificate secret. To create the guestbook-certificate secret I ran the following commands:

I used a self-signed certificate for testing. In any environment that interacts with ePHI you will need to use a certificate signed by a certificate authority.

openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout guestbook.mycluster.example.com.key -out guestbook.mycluster.example.com.crt -subj "/CN=guestbook.mycluster.example.com/O=guestbook.mycluster.example.com"

Create the secret from the contents of the certificate and key.

kubectl --namespace=guestbook create secret tls guestbook-certificate --key guestbook.mycluster.example.com.key --cert guestbook.mycluster.example.com.crt

We will also need a DNS record for the internal service. For simplicity I am using a public DNS zone hosted by AWS Route53 for the guestbook.mycluster.example.com CNAME to the internal ingress service’s load balancer. This can be done with private DNS services, but explaining how to do that is well beyond the scope of this document.

With the guestbook application modified and deployed according to its documentation along with the additional frontend-ingress and the route53 CNAME in place we can test connectivity. To do this I ran a curl request from the remote VPN device.

myvpn:~# curl --insecure https://guestbook.mycluster.example.com
<html ng-app="redis">
  <head>
    <title>Guestbook</title>
    <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css">
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.12/angular.min.js"></script>
    <script src="controllers.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/0.13.0/ui-bootstrap-tpls.js"></script>
  </head>
  <body ng-controller="RedisCtrl">
    <div style="width: 50%; margin-left: 20px">
      <h2>Guestbook</h2>
    <form>
    <fieldset>
    <input ng-model="msg" placeholder="Messages" class="form-control" type="text" name="input"><br>
    <button type="button" class="btn btn-primary" ng-click="controller.onRedis()">Submit</button>
    </fieldset>
    </form>
    <div>
      <div ng-repeat="msg in messages track by $index">
        {{msg}}
      </div>
    </div>
    </div>
  </body>
</html>

Here we can see that we are able to connect to our internal service over the VPN. This connection is fully secured using encryption in transit. From the remote VPN device - or whatever devices route through the VPN device - there is an https connection created. This connection traverses the VPN tunnel which is a second layer of encryption. The https connection exits the tunnel and travels through the load balancer. No SSL offload is performed on the load-balancer. Doing so would send unencrypted traffic to the Kubernetes cluster. Instead the https connection is SSL terminated at the ingress service. The ingress service is directly connected to the Kubernetes cluster’s encrypted overlay network. Thus you have a fully encrypted connection between applications running in separate networks over a private network link.