‘kubectl’ on WSL2 gives you “The connection to the server localhost:8080 was refused – did you specify the right host or port?” when using ‘sudo’

I ran into this problem trying to do a port-forward on port 443 in WSL2. Normally you don’t use ‘sudo’ for ‘kubectl’ commands but when it comes to port-forwarding ports under port 1024, 443 in this case, you need ‘sudo’ to get your OS to accept the binding of the port

The solution for me was to make sure the root user had access to the .kube/config file of my normal user. I did this via the environment variable KUBECONFIG:

1. Open a root shell

sudo su

2. Export the KUBECONFIG with a path to my regular users .kube/config

export KUBECONFIG=/home/niklas/.kube/config

3. Do the port-forward to port 443 (or anything else that needs root access)

kubectl port-forward -n ingress-nginx service/ingress-nginx-controller 443:443

I wasn’t looking for a permanent solution so this worked for the few tests I needed to do while setting up my Ingress for mTLS authentication

Tested on ‘kubectl’ 1.26, WSL2 with Ubuntu 20.08 and Kubernetes v1.26 on Minikube

Setup a simple Wiremock service in Kubernetes

Wiremock is a great tool for many things and especially black box testing. I’m here going to show a small and simple way to setup a Wiremock implementation in Kubernetes

First we need a Deployment of the Wiremock application:

# Deploy wiremock to Kubernetes
apiVersion: apps/v1
kind: Deployment
metadata:
  name: wiremock
  labels:
    app: wiremock
spec:
  replicas: 1
  selector:
    matchLabels:
      app: wiremock
  template:
    metadata:
      labels:
        app: wiremock
    spec:
      containers:
        - name: wiremock
          image: rodolpheche/wiremock
          ports:
            - containerPort: 8080
          volumeMounts:
            - name: mappings
              mountPath: /home/wiremock/mappings
            - name: files
              mountPath: /home/wiremock/__files
      volumes:
        - name: mappings
          configMap:
            name: wiremock-mappings
        - name: files
          configMap:
            name: wiremock-files

Then we need a Service to expose Wiremock to the cluster

apiVersion: v1
kind: Service
metadata:
  name: wiremock
spec:
    selector:
        app: wiremock
    ports:
        - protocol: TCP
          port: 8080
          targetPort: 8080

Two ConfigMaps for configuration and files:

apiVersion: v1
kind: ConfigMap
metadata:
  name: wiremock-mappings
data:
    mappings.json: |
        {
            "request": {
                "method": "GET",
                "url": "/api/v1/hello"
            },
            "response": {
                "status": 200,
                "bodyFileName": "hello.json",
                "headers": {
                    "Content-Type": "application/json"
                }
            }
        }
        
---

apiVersion: v1
kind: ConfigMap
metadata:
  name: wiremock-files
data:
    hello.json: |
        {
        "Hello": "World"
        }
        

And finally a call to the mock to see that everything works as expected:

 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: check-wiremock
  labels:
    app: check-wiremock
spec:
    replicas: 1
    selector:
        matchLabels:
          app: check-wiremock
    template:
        metadata:
          labels:
            app: check-wiremock
        spec:
          containers:
            - name: check-wiremock
              image: cosmintitei/bash-curl
              imagePullPolicy: Always
              command: ["/bin/sh", "-c", "while true; do date; curl -sS wiremock:8080/api/v1/hello; sleep 10; done"]

You should now see the payload from the Wiremock application every ten second in the check-wiremock applications log

Tested in Minikube v1.29.0

One keystore, many applications in a Kubernetes environment

Mutual TLS (mTLS) is a good way to secure your sensitive information when it travels over the Internet. One draw-back is that certificates needs to be renewed every now and then and if you have many applications using the same certificate chain, eg. a company with many micro services that handle sensitive information, you often find yourself needing to change the key store in many applications every time the certificate reaches its expiry. One way to handle this in a Kubernetes environment is to have all the micro services using the same key store via a Secrets or ConfigMap object.

Here is how to set it up:
1. Create a Secret (or ConfigMap) with the key stores you need (I’ve also added a trust store here):

kubectl create secret generic shared-trust-and-key-stores --from-file=keystore.p12 --from-file=truststore.jks

2. (Optional) Create a Secret to hold the pass phrases for the key stores

kubectl create secret generic shared-trust-and-key-store-credentials --from-literal=truststore_password=secret1 --from-literal=key_password=secret2 --from-literal=keystore_password=secret3

3. For every application setup a volume and mount the Secret (or ConfigMap) into that volume:

...
containers:
  - name: mypod
    image: myimage
    volumeMounts:
    - name: shared-keystores
      mountPath: "/etc/ssl"
  volumes:
  - name: shared-keystores
    secret:
      secretName: shared-trust-and-key-stores
...

4. (Optional) Map the pass phrase Secret as environment variables in the pod

...
containers:
  - name: mypod
    image: myimage
    env:
    - name: TRUSTSTORE_PASSWORD
      valueFrom:
        secretKeyRef:
          name: shared-trust-and-key-store-credentials
          key: truststore_password
    - name: KEY_PASSWORD
      valueFrom:
        secretKeyRef:
          name: shared-trust-and-key-store-credentials
          key: key_password
    - name: KEYSTORE_PASSWORD
      valueFrom:
        secretKeyRef:
          name: shared-trust-and-key-store-credentials
          key: keystore_password
...

Now in our application all we have to do is to point it to /etc/ssl for our key stores
* key store: /etc/ssl/keystore.p12
* trust store: /etc/ssl/truststore.jks

and if you are using the shared-trust-and-key-stores-credetials you will find the pass phrases as environment variables called:
* KEY_PASSWORD
* KEYSTORE_PASSWORD
* TRUSTSTORE_PASSWORD

When the time comes for renewing the certificates you only have to change in one place

Tested on WMVare Tansu v1.23.8