kernelパラメタを更新するのに使用するsysctl
とAnsibleのsysctlモジュールについて、設定ファイルと読み込みの動作について備忘録。
sysctl_setパラメタについては不明点あり。
実行環境
$ ansible --version ansible 2.9.6 config file = /home/zaki/ansible/initialize-kubeadm-ansible/ansible.cfg configured module search path = [u'/home/zaki/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules'] ansible python module location = /usr/lib/python2.7/site-packages/ansible executable location = /usr/bin/ansible python version = 2.7.5 (default, Aug 7 2019, 00:51:29) [GCC 4.8.5 20150623 (Red Hat 4.8.5-39)] $ cat /etc/redhat-release CentOS Linux release 7.7.1908 (Core)
sysctl CLIコマンドについて
値の適用について使用するのは主に以下
sysctl -w について
引数無しで実行すると
# sysctl -w sysctl: no variables specified Try `sysctl --help' for more information.
これは引数に適用したい設定値を与えてコマンドラインでパラメタ設定を行うオプション。
# cat /proc/sys/net/ipv4/ip_forward 0 # sysctl -w net.ipv4.ip_forward=1 net.ipv4.ip_forward = 1 # cat /proc/sys/net/ipv4/ip_forward 1
この通り。
つまり、rebootすれば消えてしまう状態。
sysctl -p について
引数無しで実行すると
# grep -v "^#" /etc/sysctl.conf net.ipv4.ip_forward = 1 # cat /proc/sys/net/ipv4/ip_forward 0 # sysctl -p net.ipv4.ip_forward = 1 # cat /proc/sys/net/ipv4/ip_forward 1
この通り、引数無しだとデフォルトで/etc/sysctl.conf
が読み込まれる。
引数を指定することで、任意のファイルでパラメタの設定が可能。
# cat /proc/sys/net/bridge/bridge-nf-call-iptables 0 # cat /proc/sys/net/bridge/bridge-nf-call-ip6tables 0 # cat /etc/sysctl.d/k8s.conf net.bridge.bridge-nf-call-iptables=1 net.bridge.bridge-nf-call-ip6tables=1 # sysctl -p /etc/sysctl.d/k8s.conf net.bridge.bridge-nf-call-iptables = 1 net.bridge.bridge-nf-call-ip6tables = 1 # cat /proc/sys/net/bridge/bridge-nf-call-iptables 1 # cat /proc/sys/net/bridge/bridge-nf-call-ip6tables 1
sysctl --system について
システム上の全設定ファイルが適用される。
man
から引用
--system Load settings from all system configuration files. Files are read from directories in the following list in given order from top to bottom. Once a file of a given filename is loaded, any file of the same name in subsequent directories is ignored. /run/sysctl.d/*.conf /etc/sysctl.d/*.conf /usr/local/lib/sysctl.d/*.conf /usr/lib/sysctl.d/*.conf /lib/sysctl.d/*.conf /etc/sysctl.conf
Ansibleのsysctlモジュールについて
以上のsysctl
コマンドの読み込み動作を踏まえて
保存先のファイル
sysctl_file
で指定できる。
デフォルトの/etc/sysctl.confに保存したい
sysctl: sysctl_file: /etc/sysctl.conf
で指定できる。
ただしこのパラメタのデフォルト値なので省略可能。
任意の設定ファイルに保存したい
例えば/etc/sysctl.d/k8s.conf
に設定を保存したい場合は
sysctl: sysctl_file: /etc/sysctl.d/k8s.conf
と書けばOK
値の即時適用
reload
で指定する。
true
: 設定ファイルに設定値が保存され、設定も反映されて/proc/sys
以下の値が更新false
: 設定ファイルに設定値が保存されるが、設定は適用されず/proc/sys
以下の値は変更されない
なので基本はtrue/yes
で良いし、デフォルトはそうなっている。
(未解決)sysctl_set って何
で実はこれが分からなく、デフォルトはoffだしパラメタの説明を見ても
Verify token value with the sysctl command and set with -w if necessary
の意味がピンと来なかった。
で、結局ソースを見たんだけど、v2.9ベースだとset_proc
というフラグがonになっている。
更に読んでいくと、この_set_token_value()関数をコールしていることが分かる。
内容をよく見ると、sysctl -w key=value
を実行している。
が、つまりどういうことだってばよ?
reload:falseでキー誤りの場合
結局よくわからず、パラメタの説明の "Verify token value" と勘を頼りに「誤ったカーネルパラメタを指定」して、かつreload: false
で即時適用をオフにしてみるとエラーで停止する動作をするものだった。
つまり
tasks: - sysctl: name: net.ipv4.ip_forwar value: '1' state: present sysctl_set: false reload: false
という誤ったキー(forward
でなくd
が抜けてforwar
になってる)にすると、sysctl_set: false
(デフォルト)の場合は誤ったキー設定で/etc/sysctl.conf
が作成されるてエラーにもならずに処理が行われる。
が
tasks: - sysctl: name: net.ipv4.ip_forwar value: '1' state: present sysctl_set: true reload: false
と、sysctl_set
をtrue
にすると、
TASK [sysctl] ****************************************************************** fatal: [master02]: FAILED! => changed=false ansible_facts: discovered_interpreter_python: /usr/bin/python msg: |- setting net.ipv4.ip_forwar failed: sysctl: cannot stat /proc/sys/net/ipv4/ip_forwar: No such file or directory PLAY RECAP ********************************************************************* master02 : ok=0 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
という風にエラーでAnsibleが止まるようになる。
ただし、一見便利そうに見えて、誤ったキー文字列のまま設定ファイルへは出力されてしまう。
前述d
が抜けたip_forwa
の例であれば
net.ipv4.ip_forwar=1
と/etc/sysctl.conf
に書き込まれる。
reload:falseでキーも正しい場合
キーが間違ってる場合の動作を踏まえると、reload:false
で即時反映をオフにしてるつもりでもsysctl_set:true
にすれば(内部のsysctl -w
の動作で)即時反映されるのでは?と思い確認。
tasks: - sysctl: name: net.ipv4.ip_forward value: '1' state: present sysctl_set: true reload: false
上記のタスク設定であれば、予想通り/proc/sys/net/ipv4/ip_forward
の値は1
になる。
そもそもreload:trueでキー誤りの場合
sysctl_set:false
でreload:true
の場合(どちらもデフォルト)
tasks: - sysctl: name: net.ipv4.ip_forwar value: '1' state: present sysctl_set: false reload: true
このタスク(d
が抜けてforwar
になってる)を動かすと、
TASK [sysctl] ****************************************************************** fatal: [master02]: FAILED! => changed=false ansible_facts: discovered_interpreter_python: /usr/bin/python msg: |- Failed to reload sysctl: sysctl: cannot stat /proc/sys/net/ipv4/ip_forwar: No such file or directory PLAY RECAP ********************************************************************* master02 : ok=0 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
結局キー誤りでエラーになる。
なるほどわからん。。
set_token_value()のコールが設定ファイル書き込み処理より先に実行されれば事前チェックになりそうではあるけど、このパラメタの本来の主旨を把握できてないので何とも。 (そもそもAnsibleでカーネルパラメタの設定が妥当かチェックする機能が必要かどうかという話もあるし)
調査の発端
なんでこんなの調べてるかというと、kubeadmを使ったKubernetes環境構築の事前設定に
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf net.bridge.bridge-nf-call-ip6tables = 1 net.bridge.bridge-nf-call-iptables = 1 EOF sudo sysctl --system
という手順があり、Ansible対応しようとした際にsysctlモジュールを正しく使うにはどうすればいいのかなと調べてたらパラメタの機能がわからなかったので調べてみた、という話。
やりたいことを実現するだけなら、とりあえずsysctl_set
はデフォルトのオフで大丈夫そうだけどね。