Methods of Verifying Kubernetes Configuration

12/7/2019

I've been working on a small side project to try and learn Kubernetes. I have a relatively simple cluster with two services, an ingress, and working on adding a Redis database now. I'm hosting this cluster in Google Kubernetes Engine (GKE), but using Minikube to run the cluster locally and try everything out before I commit any changes and push them to the prod environment in GKE.

During this project, I have noticed that GKE seems to have some slight differences in how it wants the configuration vs what works in Minikube. I've seen this previously with ingresses and now with persistent volumes.

For example, to run Redis with a persistent volume in GKE, I can use:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: chatter-db-deployment
  labels:
    app: chatter
spec:
  replicas: 1
  selector:
    matchLabels:
      app: chatter-db-service
  template:
    metadata:
      labels:
        app: chatter-db-service
    spec:
      containers:
      - name: master
        image: redis
        args: [
          "--save", "3600", "1", "300", "100", "60", "10000",
          "--appendonly", "yes",
        ]
        ports:
        - containerPort: 6379
        volumeMounts:
        - name: chatter-db-storage
          mountPath: /data/
      volumes:
      - name: chatter-db-storage
        gcePersistentDisk:
          pdName: chatter-db-disk
          fsType: ext4

The gcePersistentDisk section at the end refers to a disk I created using gcloud compute disks create. However, this simply won't work in Minikube as I can't create disks that way.

Instead, I need to use:

      volumes:
      - name: chatter-db-storage
        persistentVolumeClaim:
          claimName: chatter-db-claim

I also need to include separate configuration for a PeristentVolume and a PersistentVolumeClaim.

I can easily get something working in either Minikube OR GKE, but I'm not sure what is the best means of getting a config which works for both. Ideally, I want to have a single k8s.yaml file which deploys this app, and kubectl apply -f k8s.yaml should work for both environments, allowing me to test locally with Minikube and then push to GKE when I'm satisfied.

I understand that there are differences between the two environments and that will probably leak into the config to some extent, but there must be an effective means of verifying a config before pushing it? What are the best practices for testing a config? My questions mainly come down to:

  1. Is it feasible to have a single Kubernetes config which can work for both GKE and Minikube?
  2. If not, is it feasible to have a mostly shared Kubernetes config, which overrides the GKE and Minikube specific pieces?
  3. How do existing projects solve this particular problem?
  4. Is the best method to simply make a separate dev cluster in GKE and test on that, rather than bothering with Minikube at all?
-- Douglas Parker
google-kubernetes-engine
kubernetes
minikube

1 Answer

12/7/2019

Yes, you have found some parts of Kubernetes configuration that was not perfect from the beginning. But there are newer solutions.

Storage abstraction

The idea in newer Kubernetes releases is that your application configuration is a Deployment with Volumes that refers to PersistentVolumeClaim for a StorageClass.

While StorageClass and PersistentVolume belongs more to the infrastructure configuration.

See Configure a Pod to Use a PersistentVolume for Storage on how to configure a Persistent Volume for Minikube. For GKE you configure a Persistent Volume with GCEPersistentDisk or if you want to deploy your app to AWS you may use a Persistent Volume for AWSElasticBlockStore.

Ingress and Service abstraction

Service with type LoadBalancer and NodePort in combination with Ingress does not work the same way across cloud providers and Ingress Controllers. In addition, Services Mesh implementations like Istio have introduced VirtualService. The plan is to improve this situation with Ingress v2 as how I understand it.

-- Jonas
Source: StackOverflow