diff --git a/data/ansible/roles/cgrates/tasks/main.yaml b/data/ansible/roles/cgrates/tasks/main.yaml index 47c66a353..2bc0908fc 100644 --- a/data/ansible/roles/cgrates/tasks/main.yaml +++ b/data/ansible/roles/cgrates/tasks/main.yaml @@ -5,7 +5,6 @@ name: "{{ cgrates_dependencies }}" state: present update_cache: yes - cache_valid_time: 86400 - name: Create cgrates directory ansible.builtin.file: diff --git a/data/ansible/roles/kafka/defaults/main.yaml b/data/ansible/roles/kafka/defaults/main.yaml index 98539662a..67d93bd48 100644 --- a/data/ansible/roles/kafka/defaults/main.yaml +++ b/data/ansible/roles/kafka/defaults/main.yaml @@ -1,5 +1,23 @@ --- -kafka_version: 3.5.0 -scala_version: 2.13 -kafka_service_state: started -kafka_service_enabled: true \ No newline at end of file +kafka_download_base_url: https://downloads.apache.org/kafka +kafka_download_validate_certs: yes +kafka_version: 3.6.0 +kafka_scala_version: 2.13 + +# The kafka user and group to create files/dirs with and for running the kafka service +kafka_create_user_group: true +kafka_user: kafka +kafka_group: kafka + +kafka_root_dir: /opt +kafka_dir: "{{ kafka_root_dir }}/kafka" +kafka_unit_path: /lib/systemd/system/kafka.service + +# Start kafka after installation +kafka_start: yes + +# Restart kafka on configuration change +kafka_restart: yes + +# A comma separated list of directories under which to store data log files +kafka_data_log_dirs: /var/lib/kafka/kraft-combined-logs diff --git a/data/ansible/roles/kafka/handlers/main.yaml b/data/ansible/roles/kafka/handlers/main.yaml new file mode 100644 index 000000000..4cdfe040c --- /dev/null +++ b/data/ansible/roles/kafka/handlers/main.yaml @@ -0,0 +1,7 @@ +--- +- name: Restart Kafka + systemd: + name: kafka + state: restarted + daemon_reload: yes + when: kafka_restart | bool diff --git a/data/ansible/roles/kafka/tasks/main.yaml b/data/ansible/roles/kafka/tasks/main.yaml index 46cc8e381..2080cf04d 100644 --- a/data/ansible/roles/kafka/tasks/main.yaml +++ b/data/ansible/roles/kafka/tasks/main.yaml @@ -6,39 +6,112 @@ state: present update_cache: yes +- name: Create kafka group + become: yes + group: + name: "{{ kafka_group }}" + state: present + system: yes + when: kafka_create_user_group | bool + +- name: Create kafka user + become: yes + user: + name: "{{ kafka_user }}" + group: "{{ kafka_group }}" + state: present + createhome: no + system: yes + when: kafka_create_user_group | bool + +- name: Check if Kafka has already been downloaded and unpacked + stat: + path: "{{ kafka_dir }}_{{ kafka_scala_version }}-{{ kafka_version }}" + register: dir + - name: Download Apache Kafka get_url: - url: "https://downloads.apache.org/kafka/{{ kafka_version }}/kafka_{{ scala_version }}-{{ kafka_version }}.tgz" - dest: "/tmp/kafka_{{ scala_version }}-{{ kafka_version }}.tgz" - mode: '0755' + url: "{{ kafka_download_base_url }}/{{ kafka_version }}/kafka_{{ kafka_scala_version }}-{{ kafka_version }}.tgz" + dest: /tmp + validate_certs: "{{ kafka_download_validate_certs }}" + when: not dir.stat.exists -- name: Extract Apache Kafka +- name: Unpack Apache Kafka become: yes unarchive: - src: "/tmp/kafka_{{ scala_version }}-{{ kafka_version }}.tgz" - dest: "/usr/local" + src: /tmp/kafka_{{ kafka_scala_version }}-{{ kafka_version }}.tgz + dest: "{{ kafka_root_dir }}" remote_src: yes - creates: "/usr/local/kafka_{{ scala_version }}-{{ kafka_version }}" + group: "{{ kafka_group }}" + owner: "{{ kafka_user }}" + when: not dir.stat.exists -- name: Ensure Kafka and Zookeeper services are created +- name: Create symlink to kafka installation directory + become: yes + file: + src: "{{ kafka_root_dir }}/kafka_{{ kafka_scala_version }}-{{ kafka_version }}" + dest: "{{ kafka_dir }}" + state: link + group: "{{ kafka_group }}" + owner: "{{ kafka_user }}" + +- name: Create directory for kafka data log files + become: yes + file: + path: "{{ item }}" + state: directory + group: "{{ kafka_group }}" + owner: "{{ kafka_user }}" + mode: 0755 + with_items: "{{ kafka_data_log_dirs.split(',') }}" + +- name: Template configuration file to kraft server.properties become: yes template: - src: "{{ item.service_file }}" - dest: "/etc/systemd/system/{{ item.service_name }}" - owner: root - group: root - mode: '0644' - loop: - - { service_file: 'zookeeper.service.j2', service_name: 'zookeeper.service' } - - { service_file: 'kafka.service.j2', service_name: 'kafka.service' } + src: server.properties.j2 + dest: "{{ kafka_dir }}/config/kraft/server.properties" + group: "{{ kafka_group }}" + owner: "{{ kafka_user }}" + mode: 0644 + notify: + - Restart Kafka -- name: Enable Kafka and Zookeeper services +- name: Check if kraft logs dir has been initialized + shell: "{{ kafka_dir }}/bin/kafka-storage.sh info -c {{ kafka_dir }}/config/kraft/server.properties" + register: storage_info + ignore_errors: yes + +- name: Generate a random UUID for KAFKA_CLUSTER_ID if necessary + command: "{{ kafka_dir }}/bin/kafka-storage.sh random-uuid" + register: kafka_cluster_id + changed_when: false + when: '"is not formatted" in storage_info.stdout' + +- name: Init kraft logs dir become: yes - systemd: - name: "{{ item }}" - state: "{{ kafka_service_state }}" - enabled: "{{ kafka_service_enabled }}" - daemon_reload: yes - loop: - - zookeeper - - kafka + shell: "{{ kafka_dir }}/bin/kafka-storage.sh format -t {{ kafka_cluster_id.stdout }} -c {{ kafka_dir }}/config/kraft/server.properties" + when: '"is not formatted" in storage_info.stdout' + +- name: Template kafka systemd service + become: yes + template: + src: kafka.service.j2 + dest: "{{ kafka_unit_path }}" + group: "{{ kafka_group }}" + owner: "{{ kafka_user }}" + mode: 0644 + notify: + - Restart Kafka + +- name: Install and start the kafka service + become: yes + service: + name: kafka + state: started + enabled: yes + when: kafka_start + +- name: Delete the kafka archive file + file: + path: /tmp/kafka_{{ kafka_scala_version }}-{{ kafka_version }}.tgz + state: absent diff --git a/data/ansible/roles/kafka/templates/kafka.service.j2 b/data/ansible/roles/kafka/templates/kafka.service.j2 index 7301b9897..23fac9d85 100644 --- a/data/ansible/roles/kafka/templates/kafka.service.j2 +++ b/data/ansible/roles/kafka/templates/kafka.service.j2 @@ -1,13 +1,17 @@ [Unit] -Description=Apache Kafka Server +Description=Apache Kafka Documentation=http://kafka.apache.org/documentation.html -Requires=zookeeper.service +Requires=network.target +After=network.target [Service] Type=simple -Environment="JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64" -ExecStart=/usr/local/kafka_{{ scala_version }}-{{ kafka_version }}/bin/kafka-server-start.sh /usr/local/kafka_{{ scala_version }}-{{ kafka_version }}/config/server.properties -ExecStop=/usr/local/kafka_{{ scala_version }}-{{ kafka_version }}/bin/kafka-server-stop.sh +ExecStart={{ kafka_dir }}/bin/kafka-server-start.sh {{ kafka_dir }}/config/kraft/server.properties +ExecStop={{ kafka_dir }}/bin/kafka-server-stop.sh +User={{ kafka_user }} +Group={{ kafka_group }} +Restart=on-abnormal [Install] WantedBy=multi-user.target +Alias=kafka.service \ No newline at end of file diff --git a/data/ansible/roles/kafka/templates/server.properties.j2 b/data/ansible/roles/kafka/templates/server.properties.j2 new file mode 100644 index 000000000..0a2f6aac3 --- /dev/null +++ b/data/ansible/roles/kafka/templates/server.properties.j2 @@ -0,0 +1,132 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# +# This configuration file is intended for use in KRaft mode, where +# Apache ZooKeeper is not present. +# + +############################# Server Basics ############################# + +# The role of this server. Setting this puts us in KRaft mode +process.roles=broker,controller + +# The node id associated with this instance's roles +node.id=1 + +# The connect string for the controller quorum +controller.quorum.voters=1@localhost:9093 + +############################# Socket Server Settings ############################# + +# The address the socket server listens on. +# Combined nodes (i.e. those with `process.roles=broker,controller`) must list the controller listener here at a minimum. +# If the broker listener is not defined, the default listener will use a host name that is equal to the value of java.net.InetAddress.getCanonicalHostName(), +# with PLAINTEXT listener name, and port 9092. +# FORMAT: +# listeners = listener_name://host_name:port +# EXAMPLE: +# listeners = PLAINTEXT://your.host.name:9092 +listeners=PLAINTEXT://:9092,CONTROLLER://:9093 + +# Name of listener used for communication between brokers. +inter.broker.listener.name=PLAINTEXT + +# Listener name, hostname and port the broker will advertise to clients. +# If not set, it uses the value for "listeners". +advertised.listeners=PLAINTEXT://localhost:9092 + +# A comma-separated list of the names of the listeners used by the controller. +# If no explicit mapping set in `listener.security.protocol.map`, default will be using PLAINTEXT protocol +# This is required if running in KRaft mode. +controller.listener.names=CONTROLLER + +# Maps listener names to security protocols, the default is for them to be the same. See the config documentation for more details +listener.security.protocol.map=CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT,SSL:SSL,SASL_PLAINTEXT:SASL_PLAINTEXT,SASL_SSL:SASL_SSL + +# The number of threads that the server uses for receiving requests from the network and sending responses to the network +num.network.threads=3 + +# The number of threads that the server uses for processing requests, which may include disk I/O +num.io.threads=8 + +# The send buffer (SO_SNDBUF) used by the socket server +socket.send.buffer.bytes=102400 + +# The receive buffer (SO_RCVBUF) used by the socket server +socket.receive.buffer.bytes=102400 + +# The maximum size of a request that the socket server will accept (protection against OOM) +socket.request.max.bytes=104857600 + + +############################# Log Basics ############################# + +# A comma separated list of directories under which to store log files +log.dirs={{ kafka_data_log_dirs }} + +# The default number of log partitions per topic. More partitions allow greater +# parallelism for consumption, but this will also result in more files across +# the brokers. +num.partitions=1 + +# The number of threads per data directory to be used for log recovery at startup and flushing at shutdown. +# This value is recommended to be increased for installations with data dirs located in RAID array. +num.recovery.threads.per.data.dir=1 + +############################# Internal Topic Settings ############################# +# The replication factor for the group metadata internal topics "__consumer_offsets" and "__transaction_state" +# For anything other than development testing, a value greater than 1 is recommended to ensure availability such as 3. +offsets.topic.replication.factor=1 +transaction.state.log.replication.factor=1 +transaction.state.log.min.isr=1 + +############################# Log Flush Policy ############################# + +# Messages are immediately written to the filesystem but by default we only fsync() to sync +# the OS cache lazily. The following configurations control the flush of data to disk. +# There are a few important trade-offs here: +# 1. Durability: Unflushed data may be lost if you are not using replication. +# 2. Latency: Very large flush intervals may lead to latency spikes when the flush does occur as there will be a lot of data to flush. +# 3. Throughput: The flush is generally the most expensive operation, and a small flush interval may lead to excessive seeks. +# The settings below allow one to configure the flush policy to flush data after a period of time or +# every N messages (or both). This can be done globally and overridden on a per-topic basis. + +# The number of messages to accept before forcing a flush of data to disk +#log.flush.interval.messages=10000 + +# The maximum amount of time a message can sit in a log before we force a flush +#log.flush.interval.ms=1000 + +############################# Log Retention Policy ############################# + +# The following configurations control the disposal of log segments. The policy can +# be set to delete segments after a period of time, or after a given size has accumulated. +# A segment will be deleted whenever *either* of these criteria are met. Deletion always happens +# from the end of the log. + +# The minimum age of a log file to be eligible for deletion due to age +log.retention.hours=168 + +# A size-based retention policy for logs. Segments are pruned from the log unless the remaining +# segments drop below log.retention.bytes. Functions independently of log.retention.hours. +#log.retention.bytes=1073741824 + +# The maximum size of a log segment file. When this size is reached a new log segment will be created. +log.segment.bytes=1073741824 + +# The interval at which log segments are checked to see if they can be deleted according +# to the retention policies +log.retention.check.interval.ms=300000 diff --git a/data/ansible/roles/kafka/templates/zookeeper.service.j2 b/data/ansible/roles/kafka/templates/zookeeper.service.j2 deleted file mode 100644 index 384fba117..000000000 --- a/data/ansible/roles/kafka/templates/zookeeper.service.j2 +++ /dev/null @@ -1,14 +0,0 @@ -[Unit] -Description=Apache Zookeeper server -Documentation=http://zookeeper.apache.org -Requires=network.target remote-fs.target -After=network.target remote-fs.target - -[Service] -Type=simple -ExecStart=/usr/local/kafka_{{ scala_version }}-{{ kafka_version }}/bin/zookeeper-server-start.sh /usr/local/kafka_{{ scala_version }}-{{ kafka_version }}/config/zookeeper.properties -ExecStop=/usr/local/kafka_{{ scala_version }}-{{ kafka_version }}/bin/zookeeper-server-stop.sh -Restart=on-abnormal - -[Install] -WantedBy=multi-user.target