Exposing HTTP

While pods are not accessible from outside the cluster, you can expose the http services provided by pods by using the Ingress controllers. We have Traefik v2 installed for this purpose. In general we don’t allow exposing non-http applications via TCP ports, but if you really need to do that, contact us on Matrix.

(Tutorial)

To expose a port in your pod, you first need to create a service for it. For the pod

apiVersion: v1
kind: Pod
metadata:
  name: my-pod
  labels:
    k8s-app: test-http
spec:
  containers:
  - name: mypod
    image: centos:centos7
    command: ["sleep", "infinity"]

The service might look like:

apiVersion: v1
kind: Service
metadata:
  labels:
    k8s-app: test-svc
  name: test-svc
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
  selector:
    k8s-app: test-http
  type: ClusterIP

Where spec.selector.<label> should match the label of the target pod (k8s-app: test-http), and targetPort should match the port you want to expose.

After that you can create the Ingress object:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  annotations:
    kubernetes.io/ingress.class: haproxy
  name: test-ingress
spec:
  rules:
  - host: test-service.nrp-nautilus.io
    http:
      paths:
      - backend:
          serviceName: test-svc
          servicePort: 80
        path: /
  tls:
  - hosts:
      - test-service.nrp-nautilus.io

You can choose the host subdomain to be whatever you want (<whatever>..nrp-nautilus.io). This is enough to have your pod served under test-service.nrp-nautilus.io.

Using my own domain name

If you need to use your own domain, you would have to also provide a valid certificate in a secret in your namespace:

apiVersion: v1
kind: Secret
metadata:
  name: my-own-hostname-tls
type: kubernetes.io/tls
data:
  ca.crt: <optional base64-encoded ca>
  tls.crt: <base64-encoded crt>
  tls.key: <base64-encoded key>

and add a section to the Ingress:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  annotations:
    kubernetes.io/ingress.class: haproxy
  name: test-ingress
spec:
  rules:
  - host: my-own-hostname.com
    http:
      paths:
      - backend:
          serviceName: test-svc
          servicePort: 80
        path: /
  tls:
  - hosts:
    - my-own-hostname.com
    secretName: my-own-hostname-tls

Create the CNAME DNS record for your domain pointing to nrp-nautilus.io (for geo-balanced multi-region DNS record) or east.nrp-nautilus.io (just the eastern region).

Auto renewing the certificate (this can only be done by cluster admin for now)

The Cert Manager installed in our cluster supports auto retrieving and updating ACME Let’s Encrypt certificates. To set up the HTTP channelge, create an issuer:

apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
  name: letsencrypt
spec:
  acme:
    email: <your_email>
    preferredChain: ""
    privateKeySecretRef:
      name: issuer-account-key
    server: https://acme-v02.api.letsencrypt.org/directory
    solvers:
    - http01:
        ingress:
          class: haproxy
          ingressTemplate:
            metadata:
              annotations:
                ingress.kubernetes.io/ssl-redirect: "false"
          serviceType: ClusterIP

And then request the new certificate:

apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  annotations:
  name: my-own-hostname-cert
spec:
  commonName: my-own-hostname.com
  dnsNames:
  - my-own-hostname.com
  issuerRef:
    kind: Issuer
    name: letsencrypt
  secretName: my-own-hostname-tls

Check the status of your certificate:

kubectl get certificate -o wide

If STATUS is not Certificate is up to date and has not expired, use kubectl describe certificate ... and kubectl describe order ... to debug the problem.

Once the certificate was issued, refer to the previous section to use one in your Ingress.