canonical / loki-k8s-operator

https://charmhub.io/loki-k8s
Apache License 2.0
10 stars 16 forks source link

`LogProxyConsumer` v1 must check promtail ports are not in use by other process #329

Closed Abuelodelanada closed 2 months ago

Abuelodelanada commented 9 months ago

Bug Description

loki_push_api has the following constants:

# These are the initial port values. As we can have more than one container,
# we use odd and even numbers to avoid collisions.
# Each new container adds 2 to the previous value.
HTTP_LISTEN_PORT_START = 9080  # even start port
GRPC_LISTEN_PORT_START = 9095  # odd start port

and in LogProxyConsumer we have the following method:

    def _generate_promtails_ports(self, logs_scheme) -> dict:
        return {
            container: {
                "http_listen_port": HTTP_LISTEN_PORT_START + 2 * i,
                "grpc_listen_port": GRPC_LISTEN_PORT_START + 2 * i,
            }
            for i, container in enumerate(logs_scheme.keys())
        }

We need to make sure the generated ports are not being used inside the POD.

To Reproduce

  1. Pack the indico charm from this branch
  2. Deploy the following bundle:
bundle: kubernetes
applications:
  indico:
    charm: ./indico_ubuntu-20.04-amd64.charm
    series: focal
    scale: 1
    constraints: arch=amd64
    reources:
      indico-image: abuelodelanada/indico:latest
      indico-nginx-image: abuelodelanada/indico-nginx:latest
  loki:
    charm: loki-k8s
    channel: edge
    revision: 109
    series: focal
    resources:
      loki-image: 88
    scale: 1
    constraints: arch=amd64
    storage:
      active-index-directory: kubernetes,1,1024M
      loki-chunks: kubernetes,1,1024M
    trust: true
  postgresql-k8s:
    charm: postgresql-k8s
    channel: 14/stable
    revision: 177
    resources:
      postgresql-image: 144
    scale: 1
    constraints: arch=amd64
    storage:
      pgdata: kubernetes,1,1024M
    trust: true
  redis-broker:
    charm: redis-k8s
    channel: stable
    revision: 7
    series: focal
    resources:
      redis-image: 1
    scale: 1
    constraints: arch=amd64
    storage:
      database: kubernetes,1,1024M
  redis-cache:
    charm: redis-k8s
    channel: stable
    revision: 7
    series: focal
    resources:
      redis-image: 1
    scale: 1
    constraints: arch=amd64
    storage:
      database: kubernetes,1,1024M
relations:
- - redis-broker:redis
  - indico:redis-broker
- - redis-cache:redis
  - indico:redis-cache
- - indico:database
  - postgresql-k8s:database
- - indico:log-proxy
  - loki:logging
  1. Check msg="error creating promtail" error="listen tcp :9080: bind: address already in use" appears in juju debug-log

Environment

juju: 3.1.6

Relevant log output

----- Logs from task 1 -----
2024-01-05T05:24:51Z INFO Most recent service output:
    level=info ts=2024-01-05T05:24:51.650245964Z caller=syslogtarget.go:108 msg="syslog listening on address" address=127.0.0.1:1514 tls=false
    level=error ts=2024-01-05T05:24:51.650698698Z caller=main.go:115 msg="error creating promtail" error="listen tcp :9080: bind: address already in use"
2024-01-05T05:24:51Z ERROR cannot start service: exited quickly with code 1
-----

Additional context

Port 9080 is used by nginx in indico-nginx container:

root@indico-0:/# lsof -nP -iTCP -sTCP:LISTEN | grep 9080
nginx      16 root    8u  IPv4 40653659      0t0  TCP *:9080 (LISTEN)
nginx      16 root    9u  IPv6 40653660      0t0  TCP *:9080 (LISTEN)
sed-i commented 9 months ago

One option is to let the user specify allowed ranges, e.g.

http: List[int] = parse("1, 2, 3, 5-10, 20:2:30")  # AI advisors give a good starting point for impl `parse`
grpc: List[int] = parse("100-200")
combos: List[Tuple[int, int]] = list(zip(http, grpc))  # terminates when shorter iter exhausted
lucabello commented 2 months ago

This won't be an issue anymore, since the LogProxyConsumer is deprecated in favor of LogForwarder.