Add custom conf file containing kernel parameter setting in /etc/sysctl.d directory
→ sysctl will apply settings from custom conf file
provisioner "file" {
source = "99-customnode.conf"
destination = "/tmp/99-customnode.conf"
}
provisioner "shell" {
inline = [
"sudo mv /tmp/99-customnode.conf /etc/sysctl.d/99-customnode.conf",
"sudo chmod 644 /etc/sysctl.d/99-customnode.conf",
]
}
Some kernel parameters were not set according to the 99-customnode.conf file.
ex) net.nf_conntrack_max =262144
( in 99-customnode.conf, net.nf_conntrack_max =1000000)
I confirmed that kube-proxy configures some of the kernel parameters in k8s document
(net.nf_conntrack_max → 32768 * 8core = 262144)
While the systemd-sysctl.service runs before the sysinit phase as an early boot service, kube-proxy is executed later because it runs under the kubelet, which belongs to the multi-user target
kube-proxy overwrites some kernel parameters
[Unit]
Description=Apply custom sysctl after kube-proxy starts
After=kubelet.service
Requires=kubelet.service
[Service]
Type=oneshot
ExecStart=/usr/local/bin/wait-and-apply-sysctl.sh
RemainAfterExit=true
[Install]
WantedBy=multi-user.target
#!/bin/bash
for i in {1..60}; do
FOUND=$(sudo crictl ps -a>/dev/null | grep kube-proxy | grep Running)
if [[ ! -z "$FOUND" ]]; then
break
fi
sleep 5
done
sysctl --load /etc/sysctl.d/99-customnode.conf
provisioner "file" {
source = "99-customnode.conf"
destination = "/tmp/99-customnode.conf"
}
provisioner "file" {
source = "wait-and-apply-sysctl.sh"
destination = "/tmp/wait-and-apply-sysctl.sh"
}
provisioner "file" {
source = "custom-sysctl.service"
destination = "/tmp/custom-sysctl.service"
}
provisioner "shell" {
inline = [
"sudo mv /tmp/99-customnode.conf /etc/sysctl.d/99-customnode.conf",
"sudo chmod 644 /etc/sysctl.d/99-customnode.conf",
"sudo mv /tmp/wait-and-apply-sysctl.sh /usr/local/bin/wait-and-apply-sysctl.sh",
"sudo mv /tmp/custom-sysctl.service /etc/systemd/system/custom-sysctl.service",
"sudo chmod +x /usr/local/bin/wait-and-apply-sysctl.sh",
"sudo systemctl enable custom-sysctl.service"
]
}
Ensuring consistency and reliability across nodes is critical.
While DaemonSets or user-data scripts offer a relatively easy way to apply kernel parameter configurations, they inherently rely on runtime execution, which can introduce variability and risk of human error.
By leveraging Packer to embed these settings into a custom AMI during the build image process, we treat our infrastructure as predictable (embracing the principles of Infrastructure as Code)
This method not only minimizes operational overhead but also significantly reduces the chance of configuration drift