I'm trying to get sshd running in my Kubernetes cluster so that I can set up a reverse proxy/ngrok tunnel per this blog post.
I've got nginx running, but I can't seem to connect to SSH.
Here's the complete Kubernetes config:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: dev-example-ingress
namespace: dev-example
annotations:
kubernetes.io/ingress.class: nginx
cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
tls:
- hosts:
- dev.example.ca
secretName: dev-example-tls
rules:
- host: dev.example.ca
http:
paths:
- backend:
serviceName: app-service
servicePort: 80
- backend:
serviceName: app-service
servicePort: 2222
---
apiVersion: v1
kind: Service
metadata:
name: app-service
namespace: dev-example
spec:
selector:
pod: my-pod-label
ports:
- name: http
protocol: TCP
port: 80
- name: ssh-tcp
protocol: TCP
port: 2222
# - name: ssh-udp
# protocol: UDP
# port: 2222
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-deployment
namespace: dev-example
spec:
revisionHistoryLimit: 3
selector:
matchLabels:
pod: my-pod-label
template:
metadata:
labels:
pod: my-pod-label
spec:
imagePullSecrets:
- name: regcred
containers:
- name: nginx
image: dreg.example.ca/example/dev.example.ca
ports:
- name: http
containerPort: 80
- name: sshd
image: linuxserver/openssh-server
ports:
- name: ssh
containerPort: 2222
env:
- name: PUID
value: '1000'
- name: PGID
value: '1000'
- name: TZ
value: America/Los_Angeles
- name: USER_NAME
value: example
- name: USER_PASSWORD
value: test
But when I try to connect it says "connection refused":
❯ ssh -p 2222 example@dev.example.ca
ssh: connect to host dev.example.ca port 2222: Connection refused
I don't know if that means I didn't expose the port properly or what.
I'm pretty sure linuxserver/openssh-server
is running on port 2222. If I run ps -aux
in that container I get:
^@root@app-deployment-5d9567dcc5-f5hq6:/# ps -aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.0 200 4 ? Ss 19:26 0:00 s6-svscan -t0 /var/run/s6/services
root 34 0.0 0.0 200 4 ? S 19:26 0:00 s6-supervise s6-fdholderd
root 277 0.0 0.0 200 4 ? S 19:26 0:00 s6-supervise openssh-server/log
root 278 0.0 0.0 200 4 ? S 19:26 0:00 s6-supervise openssh-server
mpen 280 0.0 0.0 256 4 ? Ss 19:26 0:00 s6-log n30 s10000000 S30000000 T !gzip -nq9 /config/logs/openssh
mpen 281 0.0 0.0 4384 3480 ? Ss 19:26 0:00 sshd: /usr/sbin/sshd -D -e -p 2222 [listener] 0 of 10-100 startups
root 298 0.5 0.0 2580 2304 pts/0 Ss 19:32 0:00 bash
root 307 0.0 0.0 1640 868 pts/0 R+ 19:32 0:00 ps -aux
What am I missing?
I'm open to using other ssh docker images if they work better/are easier. This is just for dev.
The ingress system only works for HTTP (some Ingress Controllers support basic TCP routing as a custom extension but you're just using the basics). SSH is not an HTTP-based protocol :) What you want instead is a Service with type LoadBalancer.
The Kubernetes Ingress
resource is not meant to support TCP or UDP services. Nonetheless, some Ingress
implementations provide mechanisms to support TCP or UDP on different ports. If you are using NGINX Ingress Controller, you can expose TCP or UDP ports by modifying ConfigMaps
.
To configure NGINX Ingress Controller to use these ConfigMaps
you need to configure them while deploying the Controller using the arguments --tcp-services-configmap
and --udp-services-configmap
. Each ConfigMap
should already be available before deploying the Controller.
You can then define your custom ports by defining a map of ports to services.
For example, if you were defining the NGINX Ingress Controller through manifest files, you should configure the DaemonSet
for the Controller like this:
apiVersion: apps/v1
kind: DaemonSet
metadata:
# metadata configuration...
spec:
# spec configuration...
containers:
- image: k8s.gcr.io/ingress-nginx/controller:$TAG
name: nginx-ingress-microk8s
# container configuration...
args:
- /nginx-ingress-controller
- --tcp-services-configmap=$(POD_NAMESPACE)/nginx-ingress-tcp-services
- --udp-services-configmap=$(POD_NAMESPACE)/nginx-ingress-udp-services
# other arguments...
Here is an example of a ConfigMap
taken directly from the docs:
apiVersion: v1
kind: ConfigMap
metadata:
name: tcp-services
namespace: ingress-nginx
data:
9000: "default/example-go:8080"
You can define any number of ports that can be exposed using this mechanic. However, I've never used this configuration with SSH to expose Syslog ports.