Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
9711141
feat(BOXP-60): add write-sdcard-image workflow for control-plane reco…
github-actions[bot] Jul 13, 2026
74638a0
fix: fix shellcheck warnings in write-sdcard-image.yml
boxp Jul 13, 2026
fc97b24
fix: add inline shellcheck disable=SC2029 before each SSH command
boxp Jul 13, 2026
ad24094
fix(write-sdcard-image): add pipefail and fix summary success condition
boxp Jul 13, 2026
4b35a74
fix: upload latest.img.xz.sha256 to S3 for integrity verification
boxp Jul 13, 2026
fb68b88
fix(write-sdcard-image): abort write when checksum is missing or unav…
boxp Jul 13, 2026
cb95d58
fix: address codex-review findings - device_path injection and concur…
boxp Jul 13, 2026
f2bcd47
fix: escape inner double-quote in SSH lsblk command (SC2027/SC2086)
boxp Jul 13, 2026
2fe8e84
Merge branch 'main' into feature/BOXP-60-sdcard-write-action
boxp-tfaction[bot] Jul 13, 2026
7c1b9e7
fix(write-sdcard-image): improve mount check and add concurrency control
github-actions[bot] Jul 13, 2026
8c75721
fix(write-sdcard): explicitly verify TYPE=part partitions after write
boxp Jul 13, 2026
0d8d367
fix(write-sdcard-image): pass DEVICE_PATH to remote SSH correctly and…
github-actions[bot] Jul 13, 2026
71ac592
feat(ansible): journald永続化をkubernetes_componentsロールに追加 [BOXP-127]
github-actions[bot] Jul 23, 2026
2c8169b
chore: merge main into feature/BOXP-127-control-plane-hardening (reso…
boxp Jul 23, 2026
1d90db6
fix(ansible): journald永続化をcontrol-plane限定に修正・収束処理とテストを追加 [BOXP-127]
boxp Jul 23, 2026
1853f1d
fix(ansible): preserve journald data when disabled
boxp Jul 23, 2026
c8294cc
fix(ansible): moleculeのverify.ymlにjournaId_persistent_storage変数を追加
boxp Jul 23, 2026
0b8d17f
docs(BOXP-127): plan.mdのjournald_persistent_storageデフォルト値を実装に合わせて修正
github-actions[bot] Jul 23, 2026
6f4d028
fix(journald): notify restart on dir create; add disabled-path molecu…
github-actions[bot] Jul 23, 2026
9a39087
fix: set Storage=volatile drop-in when journald persistence disabled
github-actions[bot] Jul 23, 2026
d208d4e
fix: revert to absent drop-in when journald persistence disabled
boxp Jul 23, 2026
a82539d
test(molecule): verify SystemMaxUse/MaxRetentionSec in drop-in and no…
boxp Jul 23, 2026
cf91b3d
fix(journald): address molecule test coverage gaps for disabled and p…
github-actions[bot] Jul 23, 2026
3277260
fix(journald): notify systemd-journald restart after purge task
github-actions[bot] Jul 23, 2026
7532ba0
chore: merge main into feature/BOXP-127-control-plane-hardening
github-actions[bot] Jul 23, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/test-ansible.yml
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ jobs:
if [ -d "$role_path/molecule" ]; then
echo "Testing role: $role_path"
cd "$role_path"
molecule test
molecule test --all
else
echo "No molecule tests found for role: $role_path, skipping"
fi
1 change: 1 addition & 0 deletions ansible/playbooks/control-plane.yml
Original file line number Diff line number Diff line change
Expand Up @@ -106,3 +106,4 @@
kubelet_cluster_dns: "{{ cluster_dns }}"
kubelet_cluster_domain: "{{ cluster_domain }}"
kubelet_node_ip: "{{ node_ip }}"
journald_persistent_storage: true
9 changes: 9 additions & 0 deletions ansible/roles/kubernetes_components/defaults/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -69,3 +69,12 @@ sysctl_config:
# Increased from default 100m CPU / 100Mi memory to accommodate ARM processor characteristics
etcd_resource_requests_cpu: "200m"
etcd_resource_requests_memory: "200Mi"

# journald persistent storage configuration
# Disabled by default; enable explicitly for control-plane nodes where persistent logs are needed.
# See playbooks/control-plane.yml for the enabling override.
journald_persistent_storage: false
# Set to true only when removing existing persistent journal history is intended.
journald_purge_persistent_logs: false
journald_system_max_use: "200M"
journald_max_retention_sec: "1month"
10 changes: 10 additions & 0 deletions ansible/roles/kubernetes_components/handlers/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,13 @@
- ansible_virtualization_type != "docker"
- chroot_build is not defined or not chroot_build
listen: "Restart kubelet"

- name: Restart systemd-journald
ansible.builtin.systemd:
name: systemd-journald
state: restarted
become: true
when:
- ansible_virtualization_type != "docker"
- chroot_build is not defined or not chroot_build
listen: "Restart systemd-journald"
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@
vars:
# Test-specific overrides for container environment
kubernetes_disable_swap: false # Skip swap operations in container
kubernetes_enable_modules: false # Skip module loading in container
kubernetes_enable_modules: false # Skip module loading in container
journald_persistent_storage: true # Validate the persistent-storage code path
49 changes: 49 additions & 0 deletions ansible/roles/kubernetes_components/molecule/default/verify.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
- name: Verify
hosts: all
gather_facts: true
vars:
journald_persistent_storage: true
tasks:
- name: Check if CRI-O is installed
ansible.builtin.package_facts:
Expand Down Expand Up @@ -144,3 +146,50 @@
that:
- "'1.32' in kubectl_version.stdout"
fail_msg: "Kubectl version is not as expected"

- name: Check if persistent journal directory exists
ansible.builtin.stat:
path: /var/log/journal
register: journal_dir

- name: Assert persistent journal directory exists
ansible.builtin.assert:
that:
- journal_dir.stat.exists
- journal_dir.stat.isdir
fail_msg: "/var/log/journal directory does not exist — journald persistent storage not configured"
when: journald_persistent_storage | bool

- name: Check if journald drop-in config exists
ansible.builtin.stat:
path: /etc/systemd/journald.conf.d/10-persistent-storage.conf
register: journald_dropin

- name: Assert journald drop-in config is absent when persistent storage is disabled
ansible.builtin.assert:
that:
- not journald_dropin.stat.exists
fail_msg: "journald persistent-storage drop-in must be absent when persistent storage is disabled"
when: not (journald_persistent_storage | bool)

- name: Assert journald drop-in config exists when persistent storage is enabled
ansible.builtin.assert:
that:
- journald_dropin.stat.exists
fail_msg: "journald drop-in /etc/systemd/journald.conf.d/10-persistent-storage.conf does not exist"
when: journald_persistent_storage | bool

- name: Read journald drop-in config
ansible.builtin.slurp:
path: /etc/systemd/journald.conf.d/10-persistent-storage.conf
register: journald_dropin_content
when: journald_persistent_storage | bool

- name: Assert journald is configured for persistent storage
ansible.builtin.assert:
that:
- "'Storage=persistent' in (journald_dropin_content.content | b64decode)"
- "'SystemMaxUse=200M' in (journald_dropin_content.content | b64decode)"
- "'MaxRetentionSec=1month' in (journald_dropin_content.content | b64decode)"
fail_msg: "journald drop-in is missing Storage=persistent, SystemMaxUse=200M, or MaxRetentionSec=1month"
when: journald_persistent_storage | bool
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
- name: Converge
hosts: all
become: true
roles:
- role: ../../../../kubernetes_components
vars:
kubernetes_disable_swap: false
kubernetes_enable_modules: false
journald_persistent_storage: false # Validate the disabled (volatile) code path
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
---
dependency:
name: galaxy
driver:
name: docker
platforms:
- name: instance
image: "geerlingguy/docker-ubuntu2404-ansible:latest"
platform: "${MOLECULE_DOCKER_PLATFORM:-linux/amd64}"
pre_build_image: true
privileged: true
volumes:
- /sys/fs/cgroup:/sys/fs/cgroup:rw
cgroupns_mode: host
command: /lib/systemd/systemd
env:
DEBIAN_FRONTEND: noninteractive
groups:
- orange_pi_zero3
provisioner:
name: ansible
inventory:
host_vars:
instance:
ansible_python_interpreter: /usr/bin/python3
hardware_type: orange_pi_zero3
architecture: arm64
verifier:
name: ansible
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
---
- name: Prepare Orange Pi Zero 3 simulation environment
hosts: all
gather_facts: true
tasks:
- name: Update package cache
ansible.builtin.package:
update_cache: true
become: true

- name: Install required packages for Orange Pi Zero 3 simulation
ansible.builtin.package:
name:
- systemd
- dbus
- init
- iproute2
- kmod
- procps
- curl
- gnupg
- ca-certificates
state: present
become: true

- name: Create kernel modules directory
ansible.builtin.file:
path: /lib/modules
state: directory
mode: '0755'
become: true

- name: Ensure systemd is running
ansible.builtin.systemd:
name: systemd-logind
state: started
become: true
failed_when: false

- name: Create SSH host keys
ansible.builtin.command: ssh-keygen -A
become: true
changed_when: false
failed_when: false

- name: Create mock kernel modules for testing
ansible.builtin.shell: |
set -o pipefail
mkdir -p /lib/modules/$(uname -r)
touch /lib/modules/$(uname -r)/modules.dep
touch /lib/modules/$(uname -r)/modules.symbols
become: true
changed_when: false
failed_when: false

- name: Mock modprobe for container environment
ansible.builtin.copy:
dest: /usr/local/bin/modprobe
content: |
#!/bin/bash
# Mock modprobe for container testing
echo "Mock modprobe: $*"
exit 0
mode: '0755'
become: true

- name: Ensure journald drop-in directory exists
ansible.builtin.file:
path: /etc/systemd/journald.conf.d
state: directory
mode: '0755'
become: true

- name: Pre-create role-managed journald drop-in (simulates prior persistent-enable run)
ansible.builtin.copy:
dest: /etc/systemd/journald.conf.d/10-persistent-storage.conf
mode: '0644'
content: |
[Journal]
Storage=persistent
SystemMaxUse=200M
MaxRetentionSec=1month
become: true

- name: Pre-create /var/log/journal to simulate existing persistent journal
ansible.builtin.file:
path: /var/log/journal
state: directory
mode: '2755'
become: true

- name: Create a sentinel file inside /var/log/journal to confirm non-destructive behavior
ansible.builtin.copy:
dest: /var/log/journal/.keep
content: "pre-existing log marker"
mode: '0644'
become: true
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
---
- name: Verify journald disabled path
hosts: all
gather_facts: false
tasks:
- name: Stat journald drop-in file
ansible.builtin.stat:
path: /etc/systemd/journald.conf.d/10-persistent-storage.conf
register: journald_dropin_stat

- name: Assert drop-in is absent when persistent storage is disabled
ansible.builtin.assert:
that:
- not journald_dropin_stat.stat.exists
fail_msg: >-
journald drop-in must be absent when journald_persistent_storage is false,
but the file exists at /etc/systemd/journald.conf.d/10-persistent-storage.conf

- name: Stat /var/log/journal directory
ansible.builtin.stat:
path: /var/log/journal
register: journal_dir_stat

- name: Assert /var/log/journal is preserved (non-destructive when disabled)
ansible.builtin.assert:
that:
- journal_dir_stat.stat.exists
- journal_dir_stat.stat.isdir
fail_msg: >-
/var/log/journal must be preserved when journald_persistent_storage is false —
the role must not destroy existing log data

- name: Stat sentinel file inside /var/log/journal
ansible.builtin.stat:
path: /var/log/journal/.keep
register: journal_keep_stat

- name: Assert sentinel file is preserved (pre-existing logs not deleted)
ansible.builtin.assert:
that:
- journal_keep_stat.stat.exists
fail_msg: >-
Pre-existing /var/log/journal/.keep was deleted — the role must not purge existing logs
unless journald_purge_persistent_logs is explicitly set to true
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
- name: Converge
hosts: all
become: true
roles:
- role: ../../../../kubernetes_components
vars:
kubernetes_disable_swap: false
kubernetes_enable_modules: false
journald_persistent_storage: false
journald_purge_persistent_logs: true # Validate the explicit purge opt-in path
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
---
dependency:
name: galaxy
driver:
name: docker
platforms:
- name: instance
image: "geerlingguy/docker-ubuntu2404-ansible:latest"
platform: "${MOLECULE_DOCKER_PLATFORM:-linux/amd64}"
pre_build_image: true
privileged: true
volumes:
- /sys/fs/cgroup:/sys/fs/cgroup:rw
cgroupns_mode: host
command: /lib/systemd/systemd
env:
DEBIAN_FRONTEND: noninteractive
groups:
- orange_pi_zero3
provisioner:
name: ansible
inventory:
host_vars:
instance:
ansible_python_interpreter: /usr/bin/python3
hardware_type: orange_pi_zero3
architecture: arm64
verifier:
name: ansible
Loading
Loading