Use Pomerium as a first-class secure-by-default Ingress Controller. The Pomerium Ingress Controller enables workflows more native to Kubernetes environments, such as Git-Ops style actions based on pull requests. Dynamically provision routes from Ingress resources and set policy based on annotations. By defining routes as Ingress resources you can independently create and remove them from Pomerium's configuration.

## System requirements

- Kubernetes v1.19.0 or higher, Linux nodes, `amd64` or `arm64` CPU.
- PostgreSQL 11 or higher.
- A certificate management solution, such as [cert-manager](https://cert-manager.io/).

## Deploy

```console
kubectl apply -k github.com/pomerium/ingress-controller/config/default\?ref=0-33-0
```

The Pomerium Ingress Controller is now installed into your cluster.

You need complete [Global Configuration](https://www.pomerium.com/docs/deploy/k8s/configure.md) for Pomerium to become fully operational, before you can [configure Ingress](https://www.pomerium.com/docs/deploy/k8s/ingress.md).

## Deployment variants

`config/default` is the standard install, but it is not the only one. Each path below is a complete kustomization you can apply directly in place of `config/default`, or reference as a base in your own `kustomization.yaml`.

| Path | Description |
| --- | --- |
| `config/default` | Controller and Pomerium core, CRDs, RBAC, and the bootstrap secrets job. The standard install. |
| `config/default-no-crd` | `default` without the CRD definitions, for when the CRDs are installed and owned separately — a dedicated Argo CD Application, Terraform, or a cluster admin — so the two do not compete over the schema. |
| `config/gateway-api` | `default` plus a `GatewayClass` and the `--experimental-gateway-api` flag. See [Gateway API](https://www.pomerium.com/docs/deploy/k8s/gateway-api.md). |
| `config/clustered-databroker` | Replaces the `pomerium` `Deployment` with a `StatefulSet` and adds a `pomerium-headless` `Service`, so the built-in databroker can run clustered across replicas. |
| `config/clustered-databroker-no-crd` | The clustered databroker variant, without the CRD definitions. |
| `config/http3-eks` | `default` with the `pomerium-proxy` service configured for HTTP/3 on an AWS Network Load Balancer. |
| `config/http3-gke` | `default` with the `pomerium-proxy` service configured for HTTP/3 on a GKE regional external load balancer. |
| `config/ssh` | `default` with the SSH listener enabled on port `4022`. |

For example, to install the Gateway API variant:

```console
kubectl apply -k github.com/pomerium/ingress-controller/config/gateway-api\?ref=0-33-0
```

Always pin `?ref=` to a version branch such as `0-33-0` rather than `main`, so that your installs are reproducible and you upgrade deliberately.

## Metrics

Pomerium provides a comprehensive set of Prometheus style metrics. Assuming you are running a [Prometheus Operator](https://github.com/prometheus-operator/prometheus-operator) in your cluster, you may create the following resource to enable metrics collection.

```yaml
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: pomerium
  namespace: pomerium
spec:
  endpoints:
    - port: metrics
  selector:
    matchLabels:
      app.kubernetes.io/name: pomerium
```

## Advanced

You may adjust your base installation with [`kustomize`](https://kustomize.io/), that is also accessible via the `kubectl apply -k`.

### External-DNS

`external-dns` may be used to automatically update your DNS record for the `Ingress`. The below example adjusts the `pomerium-proxy` service that automatically serves your Authentication URL, so that it's external IP address is up to date in the DNS.

```yaml title="kustomization.yaml"
resources:
  - github.com/pomerium/ingress-controller/config/default?ref=0-33-0
patches:
  - path: patch-proxy-external-dns.yaml
```

```yaml title="patch-proxy-external-dns.yaml"
apiVersion: v1
kind: Service
metadata:
  name: pomerium-proxy
  namespace: pomerium
  annotations:
    external-dns.alpha.kubernetes.io/hostname: 'authenticate.localhost.pomerium.io'
```

### Multiple Replicas

By default, Pomerium deploys with a single replica. You may scale Pomerium instances if necessary by adjusting the default deployment.

You must configure [storage persistence](https://www.pomerium.com/docs/internals/data-storage.md) in order to use more then 1 replica of Pomerium.

```yaml title="kustomization.yaml"
resources:
  - github.com/pomerium/ingress-controller/config/default?ref=0-33-0
patches:
  - path: patch-replicas.yaml
```

```yaml title="patch-replicas.yaml"
apiVersion: apps/v1
kind: Deployment
metadata:
  name: pomerium
  namespace: pomerium
spec:
  replicas: 2
```

### Set Pomerium as default `IngressClass`

An `IngressClass` may be designated as a [default controller](https://kubernetes.io/docs/concepts/services-networking/ingress/#default-ingress-class) for the cluster.

```yaml title="kustomization.yaml"
resources:
  - github.com/pomerium/ingress-controller/config/default?ref=0-33-0
patches:
  - path: patch-ingress-class.yaml
```

```yaml title="patch-ingress-class.yaml"
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
  name: pomerium
  annotations:
    ingressclass.kubernetes.io/is-default-class: 'true'
```

### Multiple controllers

In some cases, you may need to run multiple controllers, see this [community example](https://discuss.pomerium.com/t/kubernetes-ingress-multiple-idp/155/3).

### Expose Envoy Admin interface

Make sure to always restrict access to the envoy admin interface ingress.

```yaml title="kustomization.yaml"
resources:
  - github.com/pomerium/ingress-controller/config/default?ref=0-33-0
  - admin-service.yaml
  - admin-ingress.yaml
patches:
  - patch: |-
      - op: add
        path: /spec/template/spec/containers/0/args/-
        value: "--debug-admin-addr=localhost:9901"
    target:
      kind: Deployment
      name: pomerium
```

```yaml title="admin-service.yaml"
apiVersion: v1
kind: Service
metadata:
  name: envoy
spec:
  type: ExternalName
  externalName: 'localhost'
  ports:
    - protocol: TCP
      name: admin
      port: 9901
```

```yaml title="admin-ingress.yaml"
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: envoy
spec:
  ingressClassName: pomerium
  rules:
    - host: 'envoy.localhost.pomerium.io'
      http:
        paths:
          - pathType: Prefix
            path: /
            backend:
              service:
                name: envoy
                port:
                  name: admin
```

## Runtime parameters

Some parameters are only set by default via command line arguments to the container.

Normally, you would not need to adjust the container runtime parameters.

- `debug`: enable debug logging.
- `server-addr`: the address HTTPS server would bind to, `:8443` by default.
- `http-redirect-addr`: the address HTTP to HTTPS redirect server would bind to, `:8080`.
- `metrics-bind-address`: `host:port` exposes Prometheus style metrics.
- `debug-admin-addr`: `localhost:port` exposes Envoy admin interface.
