tag:blogger.com,1999:blog-78855231252380645552024-03-16T06:42:41.275+09:00技術メモメモ自宅PCにESXiを入れて検証を行うインフラエンジニアの技術メモ。tech-mmmmhttp://www.blogger.com/profile/01739191108051432575noreply@blogger.comBlogger469125tag:blogger.com,1999:blog-7885523125238064555.post-13682106700719774182024-03-10T07:38:00.002+09:002024-03-16T06:42:09.644+09:00PostfixにSPF検証機能を実装する<p>メールセキュリティの機能として知られるSPF検証は、迷惑メールなどの対策として、ほぼすべてのメールシステムで実装されている。</p>
<p>本記事では、<strong>PostfixにSPF検証機能を実装する手順</strong>を記載する。</p>
<h2 id="環境">環境</h2>
<ul>
<li>OS : AlmaLinux release 9.3</li>
<li>Postfix : 3.5.9</li>
<li>pypolicyd-spf : 2.9.3-4</li>
</ul>
<h2 id="導入手順">導入手順</h2>
<h3 id="pypolicyd-spfをインストール">1. pypolicyd-spfをインストール</h3>
<p>Postfixは単体ではSPF検証を行うことはできないので、pypolicyd-spfを<code>dnf</code>でインストールする。</p>
<pre><code># dnf install pypolicyd-spf -y
</code></pre>
<p>pypolicyd-spfの設定ファイルはシンプルな内容となっている。SPFレコードのチェックは、HELO時に記載されたドメインとMAIL FROMに記載されたドメインの2か所に対して実施し、受信拒否をすることができる。</p>
<p>今回はどちらもチェックさせるよう、そのままの設定とするが、受信拒否をさせたくない場合は、<code>Fail</code>を<code>False</code>に変更すればよい。また、このままでは内部から外部へメール送信時もSPFチェックがされてしまうので、ローカルのネットワークアドレスを<code>skip_addresses</code>に追加しておこう。</p>
<h4 id="etcpython-policyd-spfpolicyd-spf.conf">/etc/python-policyd-spf/policyd-spf.conf</h4>
<pre><code># For a fully commented sample config file see policyd-spf.conf.commented
debugLevel = 1
TestOnly = 1
HELO_reject = Fail
Mail_From_reject = Fail
PermError_reject = False
TempError_Defer = False
skip_addresses = 127.0.0.0/8,::ffff:127.0.0.0/104,::1,192.168.0.0/16
</code></pre>
<h3 id="postfixの設定">2. Postfixの設定</h3>
<p>メール受信時にpolicyd-spfに渡すための設定を実施する。</p>
<h4 id="etcpostfixmaster.cf">/etc/postfix/master.cf</h4>
<pre><code>policyd-spf unix - n n - 0 spawn
user=nobody argv=/usr/libexec/postfix/policyd-spf
</code></pre>
<h4 id="etcpostfixmain.cf">/etc/postfix/main.cf</h4>
<pre><code>smtpd_recipient_restrictions = check_policy_service unix:private/policyd-spf
policyd-spf_time_limit = 3600
</code></pre>
<p>設定後、Postfixのサービスを再起動し、設定を反映させる。</p>
<pre><code># systemctl restart postfix
# systemctl status postfix
</code></pre>
<h3 id="動作確認spf検証成功例">3. 動作確認(SPF検証成功例)</h3>
<p>実際にメールを受信した際に、SPF検証に成功している際のログを以下に記載する。</p>
<pre><code>Mar 10 06:40:54 hoge policyd-spf[57430]:
prepend Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=123.45.67.89;
helo=mail-xxxx.google.com; envelope-from=hoge@gmail.com; receiver=<UNKNOWN>
</code></pre>
<p>通過したメールのヘッダーにもSPF検証がPassしている旨追記される。</p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgr9oi9sgOXT8RQopRQ8Rw768IKth1gKL15T3fTdq1o3kR4rfwvyAEMSjnHk2PRAXNuLi2wx5M-gWVNK1WUFASVAhBdK0HciSJHSK65_-nAR2T4R7cAqftioRnlO8v3epGWXsviUUqk2T-PASAJnN9KcnEugBNZrOs5sq3RrT_oHD7hjHMW-EKGTmaHp4k/s583/001.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="321" data-original-width="583" height="352" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgr9oi9sgOXT8RQopRQ8Rw768IKth1gKL15T3fTdq1o3kR4rfwvyAEMSjnHk2PRAXNuLi2wx5M-gWVNK1WUFASVAhBdK0HciSJHSK65_-nAR2T4R7cAqftioRnlO8v3epGWXsviUUqk2T-PASAJnN9KcnEugBNZrOs5sq3RrT_oHD7hjHMW-EKGTmaHp4k/w640-h352/001.png" width="640" /></a></div>
<h3 id="動作確認spf検証ngの例">4. 動作確認(SPF検証NGの例)</h3>
<p>SPF検証がNGとなる場合は、HELOとMAIL FROMの場合で若干メッセージが異なるため、2パターンをそれぞれ記載する。</p>
<h4 id="heloのspf検証ng">HELOのSPF検証NG</h4>
<pre><code>550 5.7.23 <tech-mmmm@hoge.tech-mmmm.com>:
Recipient address rejected: Message rejected due to: SPF fail - not authorized.
Please see http://www.openspf.net/Why?s=helo;id=example.com;ip=192.168.111.1;r=<UNKNOWN>
</code></pre>
<h4 id="mail-fromのspf検証ng">MAIL FROMのSPF検証NG</h4>
<pre><code>550 5.7.23 <tech-mmmm@hoge.tech-mmmm.com>:
Recipient address rejected: Message rejected due to: SPF fail - not authorized.
Please see http://www.openspf.net/Why?s=mfrom;id=from@hoge.tech-mmmm.com;ip=192.168.111.1;r=<UNKNOWN>
</code></pre>
<p>以上で、PostfixにSPF検証機能を実装する手順は完了となる。</p><h2 style="text-align: left;">更新履歴</h2><p></p><ul style="text-align: left;"><li>2024/3/10 新規作成</li><li>2024/3/16 skip_addressesの記載を追記</li></ul><p></p>
tech-mmmmhttp://www.blogger.com/profile/01739191108051432575noreply@blogger.com0tag:blogger.com,1999:blog-7885523125238064555.post-65154495073124200982024-02-24T17:19:00.003+09:002024-02-24T17:19:53.493+09:00Raspberry Pi 4上のUbuntuにKubernetesを構築する<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEik0H3FTwgAjYI7UaKcIhhH_ZHflTVyv6C-0RH-HqJsIUt-3Mougwqgqyt45ldIZBSYfqRrNv2iT4mdJY9xMGWTWrchFEuDiEfd3K8nvtjV0IkF0eMeKAoXiTiMiAJex1KYu98JL0k0hQN9P4P4C0Lm9IpxXDtzUPq9emkocJAwm5je_E9nvN3HlLrfcuw/s860/20240209_124950-02.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" data-original-height="554" data-original-width="860" height="258" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEik0H3FTwgAjYI7UaKcIhhH_ZHflTVyv6C-0RH-HqJsIUt-3Mougwqgqyt45ldIZBSYfqRrNv2iT4mdJY9xMGWTWrchFEuDiEfd3K8nvtjV0IkF0eMeKAoXiTiMiAJex1KYu98JL0k0hQN9P4P4C0Lm9IpxXDtzUPq9emkocJAwm5je_E9nvN3HlLrfcuw/w400-h258/20240209_124950-02.jpg" width="400" /></a></div><p></p><p>本ブログでは、数回に分けてKubernetesの構築手順を記載してきた。</p>
<ul>
<li><a href="https://tech-mmmm.blogspot.com/2023/03/kubernetes-cri-dockerd.html">Kubernetes構築手順① (cri-dockerdを使ってコントロールプレーンを構築)</a></li>
<li><a href="https://tech-mmmm.blogspot.com/2023/03/kubernetes.html">Kubernetes構築手順② (ワーカーノードを追加)</a></li>
<li><a href="https://tech-mmmm.blogspot.com/2023/03/kubernetes-docker.html">Kubernetes構築手順③ (マニフェストファイルを使ってDockerコンテナをデプロイ)</a></li>
<li><a href="https://tech-mmmm.blogspot.com/2023/06/kubernetes.html">Kubernetes構築手順④ (コントロールプレーンを冗長構成にする)</a></li>
</ul>
<p>今回は、<strong>Raspberry Pi 4上のUbuntuに対してKubernetesを構築する手順</strong>を記載する。</p>
<h2 id="環境">環境</h2>
<p>今回の手順を検証した環境は以下となる。</p>
<ul>
<li>HW: Raspberry Pi 4 Model B(RAM 4GB)</li>
<li>OS: Ubuntu 22.04.4 LTS</li>
<li>コンテナランタイム: Docker : 24.0.1</li>
<li>CRI: cri-dockerd: 0.3.10-dev</li>
<li>Kubernetes: v1.28.5</li>
</ul>
<h2 id="手順">手順</h2>
<h3 id="dockerのインストール">1. Dockerのインストール</h3>
<p>Dockerのインストールは<code>apt</code>を使って実施するが、その際に利用する前提パッケージを先にインストールする。</p>
<pre><code>sudo apt install apt-transport-https ca-certificates curl software-properties-common
</code></pre>
<p>Dockerのリポジトリを登録する。以前は<code>apt-key</code>コマンドでも同様の登録ができてが、現在は非推奨となっていることから、<code>curl</code>でキー情報を入手し、登録する手順を実施する。</p>
<pre><code>sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
</code></pre>
<p>Docker CEやその他必要となるパッケージをインストールする。</p>
<pre><code>sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
</code></pre>
<p>Dockerの初期設定として、<code>daemon.json</code>を作成する。</p>
<pre><code>$ sudo vi /etc/docker/daemon.json
{
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m"
},
"storage-driver": "overlay2",
"insecure-registries": [
"192.168.11.50"
]
}
</code></pre>
<p>Dockerのサービスを起動する。</p>
<pre><code>sudo systemctl daemon-reload
sudo systemctl enable docker
sudo systemctl restart docker
</code></pre>
<h3 id="kubernetesインストール">2. Kubernetesインストール</h3>
<p>Dockerと同様、Kubernetesも<code>apt</code>でインストールするため、リポジトリを登録する。</p>
<h4 id="kubernetes-1.28.xを使用する場合">Kubernetes 1.28.xを使用する場合</h4>
<pre><code>curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.28/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring_1.28.gpg
echo \
'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.28/deb/ /' | \
sudo tee /etc/apt/sources.list.d/kubernetes_1.28.list
sudo apt update
</code></pre>
<h4 id="kubernetes-1.29.xを使用する場合">Kubernetes 1.29.xを使用する場合</h4>
<pre><code>curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.29/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
echo \
'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.29/deb/ /' | \
sudo tee /etc/apt/sources.list.d/kubernetes.list
sudo apt update
</code></pre>
<p>kubelet、kubeadm、kubectlをインストールする。今回は既存のKubernetesクラスターに追加するため、バージョンを1.28.5に固定している。さらに<code>apt-mark hold</code>をすることで、インストールしたパッケージが想定されないタイミングでバージョンアップされないようにしている。</p>
<pre><code>sudo apt-get install kubelet=1.28.5-1.1 kubeadm=1.28.5-1.1 kubectl=1.28.5-1.1
sudo apt-mark hold kubelet kubeadm kubectl
</code></pre>
<p>kubeletのサービスを起動する。</p>
<pre><code>sudo systemctl daemon-reload
sudo systemctl enable kubelet
sudo systemctl restart kubelet
</code></pre>
<h3 id="swap無効化">3. Swap無効化</h3>
<p>Kubernetesの前提条件として、Swapを無効化する必要がある。Raspberry PiのUbuntuの場合は、そもそもSwapが設定されておらず、totalの値が0になっているため、このまま作業を続行する。</p>
<pre><code>$ free
total used free shared buff/cache available
Mem: 3880992 226264 2100932 3552 1553796 3472052
Swap: 0 0 0
</code></pre>
<h3 id="cri-dockerdインストール">4. cri-dockerdインストール</h3>
<p>cri-dokerdはGo言語でコンパイルする必要があるため、まずはGoのインストールを行う。なお、Ubuntuの標準リポジトリのGoはバージョンが古いため、<a href="https://launchpad.net/ubuntu/+ppas">PPA (Personal Package Archives)</a>のリポジトリ追加を行ったうえでインストールを行う。</p>
<pre><code>sudo add-apt-repository ppa:longsleep/golang-backports
sudo apt update
sudo apt install golang-go
</code></pre>
<p>なお、今回のインストールされたGoのバージョンは、1.21.7となる。</p>
<pre><code>$ go version
go version go1.21.7 linux/arm64
</code></pre>
<p>cri-dockerdのビルドと配置を行う。</p>
<pre><code>go build -o bin/cri-dockerd
sudo install -o root -g root -m 0755 bin/cri-dockerd /usr/local/bin/cri-dockerd
sudo cp -a packaging/systemd/* /etc/systemd/system
sudo sed -i -e 's,/usr/bin/cri-dockerd,/usr/local/bin/cri-dockerd,' /etc/systemd/system/cri-docker.service
</code></pre>
<p>cri-dockerdのサービスを起動する。</p>
<pre><code>sudo systemctl daemon-reload
sudo systemctl enable cri-docker.service
sudo systemctl start cri-docker.socket
</code></pre>
<h3 id="kubernetes起動">5. Kubernetes起動</h3>
<p>最後にKubernetesを起動するが、初めてKubernetesクラスターを構成する場合は<code>kubeadm init</code>を、既存のクラスターに参加する場合は<code>kubeadm join</code>を行う。</p>
<p>それぞれ、過去記事を参考に対応をいただきたい。</p>
<h4 id="新規にkubernetesクラスターを構成する場合">新規にKubernetesクラスターを構成する場合</h4>
<ul>
<li><a href="https://tech-mmmm.blogspot.com/2023/03/kubernetes-cri-dockerd.html">Kubernetes構築手順① (cri-dockerdを使ってコントロールプレーンを構築)</a></li>
</ul>
<h4 id="既存のkubernetesクラスターに参加する場合">既存のKubernetesクラスターに参加する場合</h4>
<ul>
<li><a href="https://tech-mmmm.blogspot.com/2023/12/kubernetes.html">Kubernetesにてノードの削除・追加を行う</a></li>
</ul>
<p>今回は既存のクラスターに参加した。結果、以下の通りUbuntu 22.04.4 LTSのノードがKubernetesに登録できた。</p>
<pre><code>$ kubectl get node -o=wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
t1015rasp Ready control-plane 26h v1.28.5 192.168.3.5 <none> Ubuntu 22.04.4 LTS 5.15.0-1046-raspi docker://25.0.3
t3051kube Ready control-plane 276d v1.28.5 192.168.3.1 <none> AlmaLinux 8.6 (Sky Tiger) 4.18.0-372.9.1.el8.x86_64 docker://24.0.6
t3052kube Ready control-plane 276d v1.28.5 192.168.3.2 <none> AlmaLinux 8.6 (Sky Tiger) 4.18.0-372.9.1.el8.x86_64 docker://24.0.6
</code></pre>
<p>以上で、Raspberry Pi 4上のUbuntuに対してKubernetesを構築する手順は完了となる。</p>
tech-mmmmhttp://www.blogger.com/profile/01739191108051432575noreply@blogger.com0tag:blogger.com,1999:blog-7885523125238064555.post-71708877475259198682024-02-24T11:00:00.007+09:002024-02-24T11:00:00.138+09:00Ansibleでタスク単位でタイムアウトを設定する<p>Ansibleでタスクを実行する際に、30秒以上応答が返ってこない場合、タイムアウトでエラーとなり処理が中断されてしまう。その際に、以下のようなエラーが表示される。</p>
<pre><code>2024-02-10 13:06:29,478 p=2302695 u=root n=ansible |
persistent connection idle timeout triggered, timeout value is 30 secs.
See the timeout setting options in the Network Debug and Troubleshooting Guide.
</code></pre>
<p>Ansibleのタイムアウトはデフォルトで30秒と設定されているが、タスクによっては時間を要するものがあり、タイムアウトを長くしたい場合がある。</p>
<p>本記事では、<strong>Ansibleでタスク単位でタイムアウトを設定する方法</strong>を記載する。</p>
<h2 id="環境">環境</h2>
<p>今回の設定を確認した環境は以下の通り。</p>
<ul>
<li>OS : AlmaLinux release 8.5</li>
<li>Ansible : ansible [core 2.15.3]</li>
</ul>
<h2 id="タスク単位でタイムアウトを設定する方法">タスク単位でタイムアウトを設定する方法</h2>
<p>タスク単位でタイムアウトを設定する場合は、タスクに<code>vars</code>設定を追加し、<code>ansible_command_timeout</code>を設定する。</p>
<p>以下例はVyOSのファイアウォール設定のタスクとなるが、ルール数が多い場合、30秒では設定は完了しないことがあるため、120秒に時間を延ばしている。</p>
<pre><code># ファイアウォールルール設定
- name: Set firewall rules
vyos.vyos.vyos_firewall_rules:
config:
- afi: ipv4
rule_sets:
- name: OUTSIDE-IN-RULE
default_action: drop
rules: "{{ vyos_firewall_rule_outside }}"
- name: INSIDE-IN-RULE
default_action: drop
rules: "{{ vyos_firewall_rule_inside }}"
state: replaced
vars:
ansible_command_timeout: 120
</code></pre>
<h2 id="【参考】デフォルトのタイムアウト時間を変更する方法">【参考】デフォルトのタイムアウト時間を変更する方法</h2>
<p><code>ansible.cfg</code>で以下を記載することで、デフォルトのタイムアウト時間を変更することができる。</p>
<pre><code>[persistent_connection]
command_timeout = 30
</code></pre>
<p>以上で、Ansibleでタスク単位でタイムアウトを設定する方法は完了となる。</p><h2 style="text-align: left;">参考</h2><p><a href="https://docs.ansible.com/ansible/2.9_ja/network/user_guide/network_debug_troubleshooting.html#id11">ネットワークデバッグおよびトラブルシューティングガイド - Ansible Documentation</a></p>
tech-mmmmhttp://www.blogger.com/profile/01739191108051432575noreply@blogger.com0tag:blogger.com,1999:blog-7885523125238064555.post-1306594289550652402024-02-19T16:30:00.001+09:002024-02-23T07:43:17.219+09:00Kubernetes構築手順① (cri-dockerdを使ってコントロールプレーンを構築)<p>今までminikubeを使ってKubernetes環境を手軽に構築をしてきたが、とうとう本家Kubernetesの構築を行うことにした。</p>
<p>Kubernetes構築は数回に分けて説明する。</p>
<ul>
<li>Kubernetes構築手順① (cri-dockerdを使ってコントロールプレーンを構築) ★本記事</li>
<li><a href="https://tech-mmmm.blogspot.com/2023/03/kubernetes.html">Kubernetes構築手順② (ワーカーノードを追加)</a></li>
<li><a href="https://tech-mmmm.blogspot.com/2023/03/kubernetes-docker.html">Kubernetes構築手順③ (マニフェストファイルを使ってDockerコンテナをデプロイ)</a></li><li><a href="https://tech-mmmm.blogspot.com/2023/06/kubernetes.html">Kubernetes構築手順④ (コントロールプレーンを冗長構成にする)</a></li>
</ul>
<p>本記事では、<strong>Kubernetesの管理機能であるコントールプレーンの構築手順</strong>を記載する。</p>
<p>なお、Kubernetesを利用する際は、CRI (Container Runtime Interface)と呼ばれるコンテナを操作するためのインタフェースを指定する必要がある。CRIにはcontainerd、CRI-O、Dockerなど選択できるが、今回は<strong>Docker用のCRIである「cri-dockerd」を利用</strong>する。</p>
<h2 id="環境">環境</h2>
<p>以下に今回構築する各種ソフトウェアのバージョンを記載する。</p>
<ul>
<li>ホストOS : AlmaLinux 8.6</li>
<li>Docker : 23.0.1</li>
<li>cri-dockerd: 0.3.1-dev</li>
<li>Kubernetes: v1.26.2</li>
</ul>
<p>なお、私の環境ではインターネット接続時にプロキシ接続が必要となるため、プロキシ経由で接続するための設定も併せて行っている。</p>
<p>今回の構成の概要図を以下に記載する。</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiuBLDof7AjwDPzD9ftAGOJRgXSDFDyWfV1UoPeCY4I-bDTNCL-GI0dT2xDgoDmB9TlhSiGYtYoaiasnn9ue-DIH3RY-wDjokBER_iTR6hue6tF18g5JuE4Zus0oXDD-dwxVHh4cbgj9cxzRUhMZUQdLn5l_ionl7NoPYkNs5N9MGFkNIINmK4FprBo/s3071/%E6%A7%8B%E6%88%90%E5%9B%B31.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1516" data-original-width="3071" height="316" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiuBLDof7AjwDPzD9ftAGOJRgXSDFDyWfV1UoPeCY4I-bDTNCL-GI0dT2xDgoDmB9TlhSiGYtYoaiasnn9ue-DIH3RY-wDjokBER_iTR6hue6tF18g5JuE4Zus0oXDD-dwxVHh4cbgj9cxzRUhMZUQdLn5l_ionl7NoPYkNs5N9MGFkNIINmK4FprBo/w640-h316/%E6%A7%8B%E6%88%90%E5%9B%B31.png" width="640" /></a></div>
<h2 id="dockerインストール">Dockerインストール</h2>
<h3 id="プロキシ設定-必要な場合のみ">1. プロキシ設定 (必要な場合のみ)</h3>
<p>私の環境ではプロキシ経由でなければインターネット接続ができないため、以下の通り環境変数を設定する。プロキシの環境変数について小文字と大文字の両方を設定している理由は、本環境変数は<strong>ソフトウェアによっては小文字と大文字の区別をすることがある</strong>ため、念のため両方を設定している。</p>
<p>また、<code>no_proxy</code>の設定は、コントロールプレーンとなるホストのIPアドレスも指定している(今回であれば、192.168.11.51)。</p>
<pre><code>export http_proxy=http://192.168.33.23:8080
export https_proxy=http://192.168.33.23:8080
export no_proxy=localhost,127.0.0.1,192.168.11.51,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16
export HTTP_PROXY=http://192.168.33.23:8080
export HTTPS_PROXY=http://192.168.33.23:8080
export NO_PROXY=localhost,127.0.0.1,192.168.11.51,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16
</code></pre>
<h3 id="dockerインストール前の競合パッケージの削除">2. Dockerインストール前の競合パッケージの削除</h3>
<p>Kubernetesが利用するコンテナエンジンはDockerを用いることにする。まずは、Dockerをインストールする。</p>
<p>ただし、GUI環境をインストールしたAlmaLinuxの場合、以下の通りpodmanとcontainers-commonのパッケージが競合する旨のエラーでインストールに失敗する。</p>
<pre><code># dnf install docker-ce docker-ce-cli containerd.io -y
メタデータの期限切れの最終確認: 0:05:01 時間前の 2022年11月26日 12時46分04秒 に 実施しました。
エラー:
問題 1: インストール済パッケージの問題 podman-2:4.0.2-6.module_el8.6.0+2878+e681bc44.x86_64
- パッケージ podman-2:4.0.2-6.module_el8.6.0+2878+e681bc44.x86_64 には runc >= 1.0.0-57 が必要ですが、どのプロバイダーからもインストールできません
- パッケージ podman-3:4.2.0-4.module_el8.7.0+3344+484dae7b.x86_64 には runc >= 1.0.0-57 が必要ですが、どのプロバイダーからもインストールできません
~(中略)~
問題 2: インストール済パッケージの問題 containers-common-2:1-27.module_el8.6.0+2878+e681bc44.x86_64
- パッケージ containers-common-2:1-27.module_el8.6.0+2878+e681bc44.x86_64 には runc が必要ですが、どのプロバイダーからもインストールできません
- パッケージ containers-common-2:1-43.module_el8.7.0+3344+484dae7b.x86_64 には runc が必要ですが、どのプロバイダーからもインストールできません
~(中略)~
</code></pre>
<p>このような場合は、一度podmanとcontainers-commonのパッケージを削除したうえで、Dockerをインストールしよう。</p>
<pre><code># dnf remove podman containers-common
</code></pre>
<h3 id="dockerをインストール">3. Dockerをインストール</h3>
<p>Dockerのインストールは以下の通りコマンドを実行すればよい。</p>
<pre><code># dnf install yum-utils -y
# yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
# dnf install docker-ce docker-ce-cli containerd.io -y
</code></pre>
<h3 id="docker起動時の設定">4. Docker起動時の設定</h3>
<p>プロキシ環境の場合は、外部からコンテナのダウンロードができるよう、systemctlの起動設定に環境変数の設定をしておくこと。</p>
<pre><code># sed -ie '/\[Service\]/a Environment="http_proxy=http://192.168.33.23:8080" "https_proxy=http://192.168.33.23:8080" "no_proxy=localhost,127.0.0.1,192.168.11.51,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16"' /usr/lib/systemd/system/docker.service
</code></pre>
<p>また、Dockerのサービス起動時の設定ファイルである<code>daemon.json</code>を以下の通り作成する。Kubernetesを利用する場合は、以下2点を設定する必要がある。</p>
<ul>
<li><code>cgroupdriver</code>に<code>cgroupfs</code>を<code>systemd</code>に変更</li>
<li><code>insecure-registries</code>に必要に応じてプライベートのDockerコンテナレジストリを設定</li>
</ul>
<pre><code># cat << EOF > /etc/docker/daemon.json
{
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m"
},
"storage-driver": "overlay2",
"storage-opts": [
"overlay2.override_kernel_check=true"
],
"insecure-registries": [
"192.168.11.54"
]
}
EOF
</code></pre>
<h3 id="dockerサービスを起動">5. Dockerサービスを起動</h3>
<p>最後に、Dockerのサービスを起動しておく。</p>
<pre><code># systemctl daemon-reload
# systemctl start docker
# systemctl enable docker
</code></pre>
<h2 id="kubernetesインストール">Kubernetesインストール</h2>
<h3 id="kubernetesパッケージのリポジトリ設定">1. Kubernetesパッケージのリポジトリ設定</h3>
<p>Kubernetesのリポジトリとして、以下の通りファイルを作成する。</p>
<pre><code># cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://pkgs.k8s.io/core:/stable:/v1.28/rpm/
enabled=1
gpgcheck=1
gpgkey=https://pkgs.k8s.io/core:/stable:/v1.28/rpm/repodata/repomd.xml.key
#exclude=kubelet kubeadm kubectl
EOF
</code></pre>
<h3 id="kubernetesパッケージインストール">2. Kubernetesパッケージインストール</h3>
<p>Kubernetesのインストールに必要なパッケージとして、<code>kubelet</code>、<code>kubeadm</code>、<code>kubectl</code>をインストールする。また、関連して必要なパッケージである<code>iproute-tc</code>も併せてインストールする。</p>
<table>
<thead>
<tr>
<th>パッケージ</th>
<th>説明</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>kubelet</code></td>
<td>Kubernetesの各ノードにインストールされるエージェントとなり、Podの起動などを制御するサービス。</td>
</tr>
<tr>
<td><code>kubeadm</code></td>
<td>Kubernetesの構築を行うためのツール。コントロールプレーンの構築や、</td>
</tr>
<tr>
<td><code>kubectl</code></td>
<td>Kubernetesの管理を行うためのツール。</td>
</tr>
<tr>
<td><code>iproute-tc</code></td>
<td>Linux Traffic Control utilityのパッケージ。</td>
</tr>
</tbody>
</table><pre><code># dnf install kubelet kubeadm kubectl --disableexcludes=kubernetes -y
# dnf install iproute-tc -y
</code></pre>
<h3 id="kubelet起動">3. kubelet起動</h3>
<p>インストールしたkubeletのサービスを起動させておく。</p>
<pre><code># systemctl start kubelet
# systemctl enable kubelet
</code></pre>
<h3 id="swapの無効化">4. swapの無効化</h3>
<p>Kubernetesでは前提としてswapの無効化が必要となるため、無効化のコマンドを実行し、<code>/etc/fstab</code>にてswap領域をマウントしないよう設定する。</p>
<pre><code># swapoff -a
# sed -ie 's|\(^/dev/.* swap .*\)|#\1|' /etc/fstab
</code></pre>
<h2 id="cri-dockerdインストール">cri-dockerdインストール</h2>
<h3 id="前提パッケージインストール">1. 前提パッケージインストール</h3>
<p>cri-dockerdは、GitHubに公開されているソースを用いてビルドしインストールする。そのため、<code>git</code>、<code>wget</code>のパッケージをインストールする。</p>
<pre><code># dnf install git wget -y
</code></pre>
<h3 id="cri-dockrdをビルド及び配置">2. cri-dockrdをビルド及び配置</h3>
<p>cri-dockerdはgo言語を用いているため、<code>go</code>コマンドをインストールする。</p>
<p><code>go</code>コマンドをインストールするためのツールが用意されているので、ダウンロードしてインストールする。rootでコマンドを実行した場合は、<code>/root/.go/bin/go</code>にインストールされ、<code>~/.bash_profile</code>にもパスが追記される。</p>
<pre><code># mkdir /tmp/cri-dockerd
# cd /tmp/cri-dockerd
# wget https://storage.googleapis.com/golang/getgo/installer_linux
# chmod +x ./installer_linux
# ./installer_linux
# source ~/.bash_profile
</code></pre>
<p>次に、cri-dockerdのソースを<code>git clone</code>しダウンロードする。</p>
<pre><code># git clone https://github.com/Mirantis/cri-dockerd.git
</code></pre>
<p>ダウンロードしたソースをビルドし、systemdのディレクトリに配置する。</p>
<pre><code># cd cri-dockerd
# mkdir -p bin
# go build -o bin/cri-dockerd
# install -o root -g root -m 0755 bin/cri-dockerd /usr/local/bin/cri-dockerd
# cp -a packaging/systemd/* /etc/systemd/system
# sed -i -e 's,/usr/bin/cri-dockerd,/usr/local/bin/cri-dockerd,' /etc/systemd/system/cri-docker.service
</code></pre>
<h3 id="cri-dockrdを起動">3. cri-dockrdを起動</h3>
<p>cri-dockerdをサービスとして起動する。</p>
<pre><code># systemctl daemon-reload
# systemctl enable cri-docker.service
# systemctl enable --now cri-docker.socket
</code></pre>
<h2 id="kubeadmコマンドを用いてkubernetesクラスター作成">kubeadmコマンドを用いてKubernetesクラスター作成</h2>
<h3 id="kubeadmコマンド実行">1. kubeadmコマンド実行</h3>
<p><code>kubeadm</code>コマンドを用いて、Kubernetesクラスターの作成を行う。クラスターの作成は<code>kubeadm init</code>コマンドにて実施する。<strong>「Your Kubernetes control-plane has initialized successfully!」が表示されれば成功</strong>となる。</p>
<p>オプションの説明を以下に記載する。</p>
<table>
<thead>
<tr>
<th>オプション</th>
<th>説明</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>--pod-network-cidr=10.244.0.0/16</code></td>
<td>ネットワークアドオンとしてflannelを追加する際に必要となる設定となる。Pod用のクラスターネットワークのネットワークアドレスを指定する。</td>
</tr>
<tr>
<td><code>--cri-socket=unix:///var/run/cri-dockerd.sock</code></td>
<td>CRIとしてcri-dockerdを使うことを明示的に指定するために指定する。指定しない場合、containerdとcri-dockerdの2つがインストールされていることにより、<strong>「Found multiple CRI endpoints on the host」のエラーにてクラスターの作成に失敗</strong>するので注意しよう。</td>
</tr>
</tbody>
</table><pre><code># kubeadm init --pod-network-cidr=10.244.0.0/16 --cri-socket=unix:///var/run/cri-dockerd.sock
[init] Using Kubernetes version: v1.26.2
[preflight] Running pre-flight checks
[preflight] Pulling images required for setting up a Kubernetes cluster
[preflight] This might take a minute or two, depending on the speed of your internet connection
[preflight] You can also perform this action in beforehand using 'kubeadm config images pull'
~(中略)~
Your Kubernetes control-plane has initialized successfully!
To start using your cluster, you need to run the following as a regular user:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
Alternatively, if you are the root user, you can run:
export KUBECONFIG=/etc/kubernetes/admin.conf
You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
https://kubernetes.io/docs/concepts/cluster-administration/addons/
Then you can join any number of worker nodes by running the following on each as root:
kubeadm join 192.168.11.51:6443 --token bexxee.xx866gxx91sxxa69 \
--discovery-token-ca-cert-hash sha256:06d8e3077c71a3f7af2xx8d6b389d43673xx9a8axxa5d003ed8dccb356a42f80</code></pre>
<h3 id="kubernetesクラスター状態確認">2. Kubernetesクラスター状態確認</h3>
<p>Kubernetesの管理は<code>kubectl</code>コマンドを使って実施するが、そのままでは使用できないので、環境変数で設定ファイルのパスを指定しておく。</p><pre><code># export KUBECONFIG=/etc/kubernetes/admin.conf</code></pre><p>それでは、<code>kubectl</code>コマンドを使って、PodとNodeの状態を確認してみよう。以下の通り、各種コントロールプレーン用のPodと1台のNodeが表示される。</p>
<pre><code># kubectl get pod -A
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system coredns-787d4945fb-cf2sf 0/1 Pending 0 45s
kube-system coredns-787d4945fb-wkp86 0/1 Pending 0 45s
kube-system etcd-t1051kube 1/1 Running 0 59s
kube-system kube-apiserver-t1051kube 1/1 Running 0 60s
kube-system kube-controller-manager-t1051kube 1/1 Running 0 60s
kube-system kube-proxy-lscpc 1/1 Running 0 46s
kube-system kube-scheduler-t1051kube 1/1 Running 0 60s
# kubectl get node
NAME STATUS ROLES AGE VERSION
t1051kube NotReady control-plane 83s v1.26.2
</code></pre>
<p>上記を見ると、<strong>corednsがPendingのステータスとなっており、NodeのステータスもNotReadyとなっている</strong>。これはPod用のネットワークアドオンがインストールされていないために発生しており、後続の手順にて<strong>flannelをインストールするとステータスがRunningになるため、現時点では気にしなくて問題ない</strong>。</p>
<h2 id="ネットワークアドオンインストール-flannelインストール">ネットワークアドオンインストール (flannelインストール)</h2>
<h3 id="flannelインストール">1. flannelインストール</h3>
<p>Kubernetesのネットワークアドオンはいくつか選択肢があるようだが、今回はflannnelを利用する。flannelはインストール用のマニフェストファイルが公開されており、Kubernetes環境に適用するだけでインストールできる。</p>
<pre><code># cd ~
# curl -LO https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml
# kubectl apply -f kube-flannel.yml
namespace/kube-flannel created
serviceaccount/flannel created
clusterrole.rbac.authorization.k8s.io/flannel created
clusterrolebinding.rbac.authorization.k8s.io/flannel created
configmap/kube-flannel-cfg created
daemonset.apps/kube-flannel-ds created
</code></pre>
<h3 id="インストール後のpodとnodeの状態確認">2. インストール後のPodとNodeの状態確認</h3>
<p>インストール後、1分ほど待ってから再度PodとNodeの状態を確認してみよう。<strong>PendingステータスだったcorednsがRunningになり、NodeのステータスもReadyになっている</strong>はずだ。</p>
<pre><code># kubectl get pod -A
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-flannel kube-flannel-ds-8s4cq 1/1 Running 0 41s
kube-system coredns-787d4945fb-cf2sf 1/1 Running 0 2m43s
kube-system coredns-787d4945fb-wkp86 1/1 Running 0 2m43s
kube-system etcd-t1051kube 1/1 Running 0 2m57s
kube-system kube-apiserver-t1051kube 1/1 Running 0 2m58s
kube-system kube-controller-manager-t1051kube 1/1 Running 0 2m58s
kube-system kube-proxy-lscpc 1/1 Running 0 2m44s
kube-system kube-scheduler-t1051kube 1/1 Running 0 2m58s
# kubectl get node
NAME STATUS ROLES AGE VERSION
t1051kube Ready control-plane 3m17s v1.26.2
</code></pre>
<p>以上で、Kubernetesの管理機能であるコントールプレーンの構築手順は完了となる。とはいえ、これだけでは実際にコンテナを起動させることもできないため、次回以降でワーカーノードを追加していく。</p><h2 style="text-align: left;">更新履歴</h2><p></p><ul style="text-align: left;"><li>2023/3/11 新規作成</li><li>2024/2/19 リポジトリのURLを最新情報に更新</li></ul><p></p>
tech-mmmmhttp://www.blogger.com/profile/01739191108051432575noreply@blogger.com0tag:blogger.com,1999:blog-7885523125238064555.post-14695360066570435482024-02-18T13:32:00.000+09:002024-02-18T13:32:07.004+09:00VyOSをソースからビルドして、ISOイメージを作成するVyOSはRolliing releaseと呼ばれる非安定板であれば、ISOイメージを直接ダウンロードできるが、安定板は<a href="https://vyos.io/subscriptions/software">公式サイト</a>から直接ダウンロードができない状況となっている。<div><br /></div><div><b>安定板のVyOSを使いたい場合は、GitHubのソースからビルドすることで利用できる。</b><br />
<br />本記事では、<b>VyOSをソースからビルドし、ISOイメージを作成する方法</b>を記載する。なお、ビルドするバージョンはVyOS 1.3.5 (equuleus)とした。<br />
<h2 id="環境">
環境</h2>
ビルドするためには、以下環境が必要となる。<br />
<ul>
<li>dnfやaptを使用するため、インターネットに直接通信できること<br />※プロキシ環境で実施する場合は、OS、git、Dockerがインターネット通信できるように、適切にプロキシ設定を実施する必要があるが、手順が煩雑となるためお勧めできない</li>
<li>GitとDockerが動作する環境があること</li>
</ul>
今回は、AlmaLinux 9を最小インストールで構築し、そこにDockerをインストールして作業を実施してみた。<br />
<h2 id="最短でvyos-1.2.5をビルドするためのコマンド">
最短でVyOSをビルドするためのコマンド</h2>
最短でVyOSをビルドするコマンドを以下に記載する。上から順にコマンドを実行していけば、途中時間のかかる処理があるものの、2時間もあれば処理が完了するはずだ。私の環境ではCPU 1コアで2時間以内に完了した。ただし、yumやapt-getのダウンロード処理が多いため、インターネットの回線速度にも左右される。<br />
<br />
<code>git clone -b equuleus --single-branch https://github.com/vyos/vyos-build</code>の<code>-b</code>オプションでBranchをequuleusに指定し、VyOS 1.3.xを作成できるようにしている。もし、VyOS 1.2.xを利用したい場合はcruxを、VyOS 1.4.xを利用したい場合はSagittaを指定すればよい。</div><div><br /></div><div>なお、ISOイメージビルド時に--versionオプションでバージョンを指定できるが、あくまでもイメージ作成後のVyOSで表示する際のバージョン表記を指定するものとなり、実際のバージョンは<a href="https://github.com/vyos/vyos-1x">リポジトリにあるソース</a>をもとにビルドされる。したがって、--versionで指定するバージョンは、任意の名前で指定しても問題ない。<br />
<pre><code># gitをインストール
dnf install git -y
# Dockerをインストール
dnf install yum-utils -y
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
dnf install docker-ce docker-ce-cli containerd.io -y
systemctl start docker
# ソースをダウンロード
git clone -b equuleus --single-branch https://github.com/vyos/vyos-build
# ISOイメージ作成用のコンテナをビルド
cd vyos-build/
docker build -t vyos/vyos-build:equuleus docker
# コンテナにてISOイメージをビルド(--versionでビルド後のVyOSで表示させるバージョンを指定)
docker run --rm -it --privileged -v $(pwd):/vyos -w /vyos vyos/vyos-build:equuleus bash
./configure --architecture amd64 --build-type release --version 1.3.5
sudo make iso</code></pre>
完了後、/vyos/build配下を確認すると「live-image-amd64.hybrid.iso」というISOイメージが作成されており、これがVyOSのISOイメージとなる(「vyos-x.y.z-amd64.iso」のISOも存在するが同じものとなる)。本ISOには、open-vm-toolsも組み込まれており、ESXiの仮想マシンに対して本ISOイメージをマウントしてインストールを実施すれば、いつものVyOSを構築することができる。</div><div>
<pre><code>root@ad1ecd365c09:/vyos# ls -l build/*.iso
-rw-r--r--. 1 root root 373293056 Feb 10 02:29 build/live-image-amd64.hybrid.iso
-rw-r--r--. 1 root root 373293056 Feb 10 02:32 build/vyos-1.3.5-amd64.iso
</code></pre>
なお、<code>docker run</code>実行時に<code>-v $(pwd):/vyos</code>でDockerホストのディレクトリをコンテナにマウントしているため、Dockerホスト側でも同じファイルを確認・取得することができる。
<pre><code>[root@localhost vyos-build]# ls -l build/*.iso
-rw-r--r--. 1 root root 373293056 2月 10 11:29 build/live-image-amd64.hybrid.iso
-rw-r--r--. 1 root root 373293056 2月 10 11:32 build/vyos-1.3.5-amd64.iso
</code></pre>
<h2 id="参考">参考</h2>
<ul>
<li><a href="https://github.com/vyos/vyos-build">GitHub - vyos/vyos-build</a></li>
<li><a href="https://docs.vyos.io/en/crux/contributing/build-vyos.html">Building VyOS</a></li>
</ul>
<h2 id="更新履歴">
参考</h2>
<ul>
<li>2020/5/7 新規作成</li>
<li>2021/1/9 VyOS 1.2.6のバージョンに内容を修正</li><li>2024/2/17 VyOS 1.3の実施結果をふまえ更新</li><li>2024/2/18 --versionの説明を修正</li>
</ul>
</div>tech-mmmmhttp://www.blogger.com/profile/01739191108051432575noreply@blogger.com0tag:blogger.com,1999:blog-7885523125238064555.post-69301088419111173562024-02-10T15:31:00.002+09:002024-02-10T15:34:35.645+09:00OpenAI APIを使ってZabbixの障害イベントを生成AIに連携する<p>ChatGPTでおなじみのOpenAIは、OpenAI APIと呼ばれるAPIによる利用が可能となっている。APIを利用することで、<code>curl</code>コマンドなどを用いて手軽に生成AIの機能をシステムに組み込んで利用することができる。</p>
<p>本記事では、<strong>OpenAI APIを使ってZabbixの障害アラートを生成AIに連携する手順</strong>を記載する。</p>
<p>具体的には、OpenAI APIを用いて以下のプロンプトを連携し、Zabbixの障害アラートの原因の問い合わせを行う。問い合わせで得られた生成AIの応答をZabbixのメッセージとして表示できるようにする。</p>
<pre><code>Please tell me the cause of the error message below.
[障害アラートの内容]
</code></pre>
<p>なお、本記事の作成にあたり、以下の記事も参考にさせていただいた。</p>
<ul>
<li><a href="https://blog.usize-tech.com/integrate-zabbix-chatgpt-mediatype/">ZabbixとChatGPTを連携してみた(メディアタイプ編) – TechHarmony</a></li>
</ul>
<h2 id="環境">環境</h2>
<p>今回の環境は以下の通り。</p>
<ul>
<li>Zabbix 6.0.17</li>
</ul>
<p>OpenAIのアカウントを作成していない場合は、事前に作成をしておこう。ChatGPTを利用している場合は、すでにアカウント作成済みとなるため、新たにアカウント作成は不要となる。</p>
<h2 id="openai-apiのapi-keyを取得">OpenAI APIのAPI keyを取得</h2>
<h3 id="openai-api-keyの作成画面にログイン">1. OpenAI API keyの作成画面にログイン</h3>
<p>以下URLにアクセスすると、OpenAI API keyの作成画面が表示される。</p>
<ul>
<li><a href="https://platform.openai.com/account/api-keys">https://platform.openai.com/account/api-keys</a></li>
</ul>
<h3 id="api-keyを作成">2. API keyを作成</h3>
<p>「Create new secret key」ボタンを押し、API keyを作成する。</p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiwZFm29viTvFHBVYN8tpWHqn1yTUzIUU1skcthn0KOWACsYA-a6mEhy5wmCpgoDK-bt2KsrjiooOi3Z_dRrdVb7AbpqwD3nEUXANj_skD-_eklHz7eFjuH87kRHvSVyN2iY36tSu2Hh3k7LSkp7Pf5iQEveP080Wi7o0Otu9cbf8wwD7IAFTuOLMSWSK0/s800/004.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="552" data-original-width="800" height="442" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiwZFm29viTvFHBVYN8tpWHqn1yTUzIUU1skcthn0KOWACsYA-a6mEhy5wmCpgoDK-bt2KsrjiooOi3Z_dRrdVb7AbpqwD3nEUXANj_skD-_eklHz7eFjuH87kRHvSVyN2iY36tSu2Hh3k7LSkp7Pf5iQEveP080Wi7o0Otu9cbf8wwD7IAFTuOLMSWSK0/w640-h442/004.png" width="640" /></a></div>
<p>作成時にkeyの名前の入力を求められるが、未入力でも問題ない。</p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhKquSOgHIt3GGhZn_4H9nUr24T3k7yM0XSZBgaTiiligybcXBTXEIPxu4VFesGuysjvf2ZmzNuwzFa_Slvokuw41bg4nuFJiTa1rAPmP63BhhD6DLJ30oDcDmgF7BCkygTec6QLDgEqjYWIhNtIAmjJv-ZEjc9--S-a89fu9Gkim4WgJhRlrcRLElyCQc/s514/005.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="205" data-original-width="514" height="160" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhKquSOgHIt3GGhZn_4H9nUr24T3k7yM0XSZBgaTiiligybcXBTXEIPxu4VFesGuysjvf2ZmzNuwzFa_Slvokuw41bg4nuFJiTa1rAPmP63BhhD6DLJ30oDcDmgF7BCkygTec6QLDgEqjYWIhNtIAmjJv-ZEjc9--S-a89fu9Gkim4WgJhRlrcRLElyCQc/w400-h160/005.png" width="400" /></a></div>
<p>作成完了後、API keyが表示されるので、<strong>必ずコピーして控える</strong>こと。ここでコピーしておかないと、以降確認することができないため、API keyを再作成する必要がある。</p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi1tQx8fvkVwK1KoOi2_nFelGrnMfbEwXlQnZ7fe8x7cX5SJkHj7zm7wL0DhG-twVCok8UPMKuMqtAwBbXqjKi-qDNCiNqvmpXApY157E7bTrKbK5-_yVu2v6ffC_jXCFVTo83mi5sKtgP-tYppMm-kYhqe8KzGQGesnjYrTy8d09XjhIvo_Ea1ea4HPAA/s513/006.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="269" data-original-width="513" height="210" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi1tQx8fvkVwK1KoOi2_nFelGrnMfbEwXlQnZ7fe8x7cX5SJkHj7zm7wL0DhG-twVCok8UPMKuMqtAwBbXqjKi-qDNCiNqvmpXApY157E7bTrKbK5-_yVu2v6ffC_jXCFVTo83mi5sKtgP-tYppMm-kYhqe8KzGQGesnjYrTy8d09XjhIvo_Ea1ea4HPAA/w400-h210/006.png" width="400" /></a></div>
<h3 id="openai-apiの利用状況を確認">3. OpenAI APIの利用状況を確認</h3>
<p>OpenAI APIはリクエストや応答に含まれるトークンの数によって課金される。トークンは英語の場合は1単語がおおよそ1トークンとなるようだが、日本語の場合は1文字が1トークン以上の場合があるとの情報があるので注意する。</p>
<p>トークンの使用状況は以下URLから確認することができる。</p>
<ul>
<li><a href="https://platform.openai.com/account/usage">https://platform.openai.com/account/usage</a></li>
</ul>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiEXRWZknvR1Pvg8wpytxk3Lw1MmXfJOwF0-iJG7hSwJxdcCrKpAtkZL0b4v2tzTj4WjNUSQJVdxKwyd2W1VrAb6bkPNVHML44nbc28eDot3NCFsIC7eDD64Jpr4DvGUmG3I98ML-ABuszA7yA26uG8zmfspy5E56nctf8d5DBEFTq1xPjkUza1rVgJeeo/s846/001.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="776" data-original-width="846" height="588" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiEXRWZknvR1Pvg8wpytxk3Lw1MmXfJOwF0-iJG7hSwJxdcCrKpAtkZL0b4v2tzTj4WjNUSQJVdxKwyd2W1VrAb6bkPNVHML44nbc28eDot3NCFsIC7eDD64Jpr4DvGUmG3I98ML-ABuszA7yA26uG8zmfspy5E56nctf8d5DBEFTq1xPjkUza1rVgJeeo/w640-h588/001.png" width="640" /></a></div>
<p>なお、アカウントを新規作成した際は、5.00 USD分の無料利用枠がある(3か月の期限付き)。テストする際にかなりAPIを使用してみたが、それでも0.03 USDしか消費しなかったので、5.00 USDあれば検証用途としては十分だろう。</p>
<h2 id="openai-api連携用スクリプトの作成">OpenAI API連携用スクリプトの作成</h2>
<h3 id="curlによるopenai-api実行方法">1. <code>curl</code>によるOpenAI API実行方法</h3>
<p><code>curl</code>を使う場合は以下の通り実行すればOpenAI APIによる問い合わせができる。</p>
<pre><code># API keyを設定
export OPENAI_API_KEY='sk-********'
header='Content-Type: application/json'
apiurl='https://api.openai.com/v1/chat/completions'
prompt="ここに問い合わせしたい内容を記載。"
json='{"model": "gpt-3.5-turbo", "messages": [{"role": "user", "content": "'${prompt}'"}]}'
# API実行
curl ${apiurl} -sS -H "Authorization: Bearer ${OPENAI_API_KEY}" -H "${header}" -d "${json}"
</code></pre>
<p>実行結果は以下の通り。<code>.choices[0].message.content</code>がAIの回答となる。</p>
<pre><code># curl ${apiurl} -H "Authorization: Bearer ${OPENAI_API_KEY}" -H "${header}" -d "${json}"
{
"id": "chatcmpl-xxxxxxxx",
"object": "chat.completion",
"created": 1695187433,
"model": "gpt-3.5-turbo-0613",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "The OpenAI mission is to ensure that artificial general intelligence (AGI) benefits all of humanity. AGI refers to highly autonomous systems that outperform humans in most economically valuable work. OpenAI aims to build safe and beneficial AGI directly, but it also considers its mission fulfilled if its work aids others in achieving this outcome. OpenAI commits to principles of broadly distributed benefits, long-term safety, technical leadership, and cooperative orientation to achieve the positive impact of AGI on society."
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 14,
"completion_tokens": 97,
"total_tokens": 111
}
}
</code></pre>
<h3 id="スクリプト作成">2. スクリプト作成</h3>
<p><code>curl</code>によるOpenAI APIの実行方法を用いて、Zabbixの障害アラートを連携するスクリプトを以下の通り作成した。各環境に合わせて、OpenAIのAPI keyやZabbix API実行用のユーザとパスワードを設定すること。</p>
<p>障害アラートへのメッセージ追加はZabbix APIを使用する。Zabbix APIの使い方は、以下別記事を参考にしていただきたい。</p>
<ul>
<li><a href="https://tech-mmmm.blogspot.com/2019/02/zabbix-api.html">Zabbix API入門</a></li>
</ul>
<p>また、OpenAI APIで同時に多数のリクエストを実行すると、応答がうまく得られず<code>null</code>が返ってくる場合があったため、負荷分散を目的として、実行間隔制御の待機時間(最小10秒~最大120秒)を設定した。</p>
<h4 id="send_chatgpt_api.sh"><code>send_chatgpt_api.sh</code></h4>
<pre><code>#!/bin/bash
# アラート内容を引数に代入
eventid=$1
alert=$(echo $2 | sed -e 's/"/\\"/g')
# 実行間隔制御 (10秒+ランダム時間)
sleep $(( 10 + ($RANDOM % 110) ))
# API keyを設定
export OPENAI_API_KEY='sk-********'
header='Content-Type: application/json'
apiurl='https://api.openai.com/v1/chat/completions'
prompt="Zabbixで検知した以下イベントメッセージの原因及び解消方法を簡潔に教えてください。\n\n${alert}"
json='{"model": "gpt-3.5-turbo", "messages": [{"role": "user", "content": "'${prompt}'"}]}'
# API実行
result=$(curl ${apiurl} -sS -H "Authorization: Bearer ${OPENAI_API_KEY}" -H "${header}" -d "${json}")
# 出力
result_message=$(echo $result | jq -r '.choices[0].message.content')
# Zabbix APIログイン
header='Content-Type:application/json-rpc'
apiurl='http://[ZabbixサーバのURL]/zabbix/api_jsonrpc.php'
json='{"jsonrpc": "2.0","method": "user.login","params": {"user": "Admin","password": "********"},"id": 1,"auth": null}'
zbxauth=$(curl -sS -X POST -H "${header}" -d "${json}" ${apiurl} | jq -r ".result")
# Zabbix APIでイベントにメッセージ追加
json='{"jsonrpc": "2.0","method": "event.acknowledge","params": {"eventids": "'${eventid}'","action": 4,"message": "'$(echo ${result_message} | sed -e 's/"/\\"/g')'"},"auth": "'${zbxauth}'","id": 1}'
curl -sS -X POST -H "${header}" -d "${json}" ${apiurl} | jq
# Zabbix APIログオフ
json='{"jsonrpc": "2.0","method": "user.logout","params": [],"id": 4,"auth": "'$zbxauth'"}'
curl -sS -X POST -H "${header}" -d "${json}" ${apiurl} | jq
exit 0
</code></pre>
<h3 id="スクリプトをzabbixサーバに配置">3. スクリプトをZabbixサーバに配置</h3>
<p>本スクリプトは、Zabbixサーバの<code>/usr/local/bin</code>に配置し、実行権限を付与しておく。</p>
<pre><code># cp send_chatgpt_api.sh /usr/local/bin/
# chmod +x /usr/local/bin/send_chatgpt_api.sh
# ls -l /usr/local/bin/send_chatgpt_api.sh
-rwxr-xr-x 1 root root 1753 9月 23 07:41 /usr/local/bin/send_chatgpt_api.sh
</code></pre>
<p>実行方法は以下の通りとなる。</p>
<pre><code>/usr/local/bin/send_chatgpt_api.sh '[イベントID]' '[アラート内容]'
</code></pre>
<h2 id="zabbixのトリガーアクションを設定">Zabbixのトリガーアクションを設定</h2>
<h3 id="スクリプト設定">1. スクリプト設定</h3>
<p>Zabbixのスクリプト設定を以下の通り行う。</p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>設定値</th>
</tr>
</thead>
<tbody>
<tr>
<td>名前</td>
<td>Send ChatGPT</td>
</tr>
<tr>
<td>タイプ</td>
<td>スクリプト</td>
</tr>
<tr>
<td>次で実行</td>
<td>Zabbixサーバー</td>
</tr>
<tr>
<td>コマンド</td>
<td><code>/usr/local/bin/send_chatgpt_api.sh '{EVENT.ID}' '{ITEM.VALUE}'</code></td>
</tr>
</tbody>
</table><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEifkxghGJFC-_nCF1iBNGqOvN-6Gqixngv0ToBL6_PDPtO1N6MVfx-NItNUY-4RnnfeZUIxB9rMvy8HlT9iqT5lvCeWLEroUwTpTq52m8-YrGcKjA9Sojadc1_hSeEhSldZ835ONhXLselv3Q6t2Ko0X0E0eIxlMWrnfQsxgnFeLU5BDkPMplR0R4fzCmM/s944/016.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="626" data-original-width="944" height="424" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEifkxghGJFC-_nCF1iBNGqOvN-6Gqixngv0ToBL6_PDPtO1N6MVfx-NItNUY-4RnnfeZUIxB9rMvy8HlT9iqT5lvCeWLEroUwTpTq52m8-YrGcKjA9Sojadc1_hSeEhSldZ835ONhXLselv3Q6t2Ko0X0E0eIxlMWrnfQsxgnFeLU5BDkPMplR0R4fzCmM/w640-h424/016.png" width="640" /></a></div>
<h3 id="トリガーアクション設定">2. トリガーアクション設定</h3>
<p>Zabbixのトリガーアクション設定を以下の通り行う。今回は、「軽度の障害」以上の場合にスクリプトを実行するよう設定する。</p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>設定値</th>
</tr>
</thead>
<tbody>
<tr>
<td>名前</td>
<td>Send ChatGPT</td>
</tr>
<tr>
<td>実行条件</td>
<td>「メンテナンス期間外」 AND 「トリガーの深刻度 以上 軽度の障害」</td>
</tr>
</tbody>
</table><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi4SyJ-1Gtp2YEaWrkDltFVFlabt4Wcuy9AhQqsvapi3vJch8paw5BkpB3OvtZIqTA1L_clC0rfc2Se1ldVbV_ppSa8YvfWg1MQG0jVzm0KiOo_HHsFMBOU0O5cryyosTMj93lM9D8F2D4L32qi4JuwjF_ptzDH_ZB6KuEVVJKpIJUi2G-QJ84s9Fx4iJo/s956/013.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="520" data-original-width="956" height="348" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi4SyJ-1Gtp2YEaWrkDltFVFlabt4Wcuy9AhQqsvapi3vJch8paw5BkpB3OvtZIqTA1L_clC0rfc2Se1ldVbV_ppSa8YvfWg1MQG0jVzm0KiOo_HHsFMBOU0O5cryyosTMj93lM9D8F2D4L32qi4JuwjF_ptzDH_ZB6KuEVVJKpIJUi2G-QJ84s9Fx4iJo/w640-h348/013.png" width="640" /></a></div>
<p>アクションの実行内容は以下の通り、先ほど作成したスクリプトを指定する。</p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>設定値</th>
</tr>
</thead>
<tbody>
<tr>
<td>処理内容</td>
<td>Send ChatGPT</td>
</tr>
<tr>
<td>ターゲットリスト</td>
<td>Zabbix server</td>
</tr>
</tbody>
</table><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgCEZwzq4i-Lqx1J7JhWCJVSX5eOQcoVpItN8LfboTZSZe8X1-L_WkJbRgHVojfAI2fFo5C8-XFF5mkG0VsJ5VXIlGWDup5kL89DCmkm05_eM2-vBfOATkp6ttA1jdJh8khvhGpCgzVZElLWyFvmcKzt4AlHUghimdTTpCCcerzf1sXelDEZDgDoJWZ1Ao/s586/015.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="407" data-original-width="586" height="444" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgCEZwzq4i-Lqx1J7JhWCJVSX5eOQcoVpItN8LfboTZSZe8X1-L_WkJbRgHVojfAI2fFo5C8-XFF5mkG0VsJ5VXIlGWDup5kL89DCmkm05_eM2-vBfOATkp6ttA1jdJh8khvhGpCgzVZElLWyFvmcKzt4AlHUghimdTTpCCcerzf1sXelDEZDgDoJWZ1Ao/w640-h444/015.png" width="640" /></a></div>
<h2 id="動作確認">動作確認</h2>
<p>実際に障害アラートを発生させて、動作を確認してみよう。</p>
<p>例として、以下の障害アラートを発生させてみた。ポートチャネルPo1からgi3が除外されたアラートとなる。</p>
<pre><code>SNMP Trap from t1250c250 : 2024/02/10 15:11:26. .1.3.6.1.4.1.9.6.1.101.0.161
Normal General event UNKNOWN - %TRUNK-W-PORTREMOVED: Port gi3 removed from Po1 1
</code></pre>
<p>しばらくするとスクリプトが実行され、以下の通りOpenAI APIで取得した生成AIの回答がメッセージとして表示された。</p>
<pre><code>このイベントメッセージの原因は、ポートgi3がPo1 1から削除されたことです。
解決方法は、次のいずれかです。
1. ネットワーク上でポートを再接続し、Po1 1にgi3を再度追加します。
2. システムの設定を確認し、ポートが正しく構成されていることを確認します。
3. 他のネットワークデバイスとの接続に問題がある場合は、接続を確認し、
必要に応じて修正します。
これらの手順を実行することで、問題が解決する可能性があります。
ただし、具体的な状況に応じて解決方法が異なる場合もあるため、
詳細な情報があれば助かります。
</code></pre>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQuwB0tO5-hQAhZfQjz3cILlNcpb_jiIoL4mkN7OkfaNwfVE9k2rVDPUc4s5Q25t_Br1U0CC4uDvcrgCm0v2tCmSg-F25RcW4fzfQbEtr2XMowRWXOEFxFIA91SbvVtbbV6NuWmG00EKsX_3XVoZOqvREeAtu_OootoGURkZ2NTbnYgtrYZ4PvCPYCaYg/s1655/021.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="659" data-original-width="1655" height="254" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQuwB0tO5-hQAhZfQjz3cILlNcpb_jiIoL4mkN7OkfaNwfVE9k2rVDPUc4s5Q25t_Br1U0CC4uDvcrgCm0v2tCmSg-F25RcW4fzfQbEtr2XMowRWXOEFxFIA91SbvVtbbV6NuWmG00EKsX_3XVoZOqvREeAtu_OootoGURkZ2NTbnYgtrYZ4PvCPYCaYg/w640-h254/021.png" width="640" /></a></div>
<p>以上で、OpenAI APIを使ってZabbixの障害アラートを生成AIに連携する手順は完了となる。</p>
<h2 id="参考">参考</h2>
<ul>
<li><a href="https://blog.usize-tech.com/integrate-zabbix-chatgpt-mediatype/">ZabbixとChatGPTを連携してみた(メディアタイプ編) – TechHarmony</a></li><li><a href="https://platform.openai.com/docs/api-reference/introduction">API Reference - OpenAI API</a></li>
</ul><h2 style="text-align: left;">更新履歴</h2><div><ul style="text-align: left;"><li>2023/9/23 新規作成</li><li>2024/2/10 OpenAI APIに送るプロンプトを日本語に変更</li></ul></div>
tech-mmmmhttp://www.blogger.com/profile/01739191108051432575noreply@blogger.com0tag:blogger.com,1999:blog-7885523125238064555.post-33115430883156526892024-02-04T15:57:00.000+09:002024-02-04T15:57:24.243+09:00Roundcubeでメール振り分け等のフィルター機能を有効にする<p>OSSのWebメールクライアントである「Roundcube」は、標準ではメール振り分けといったメールフィルターの機能を使用することができない。</p>
<p>Roundcubeはプラグインとして、機能を追加することができる。今回は<strong>Roundcubeにて「ManageSieve」のプラグインを有効化し、フィルター機能を利用できる</strong>ようにする。</p>
<p>なお、ManageSieveを利用する際には、Dovecot PigeonholeをインストールしSieveスクリプトによるメール制御を行うことで、フィルター機能を実現することから、Postfix及びDovecot への設定追加が必要となる。</p>
<h2 id="環境">環境</h2>
<p>Roundcubeのインストール手順は以下を参照いただきたい。</p>
<ul>
<li><a href="https://tech-mmmm.blogspot.com/2023/11/roundcubeweb.html">Roundcubeを使ってWebメール環境を構築する</a></li>
</ul>
<p>Roundcubeはあくまでもメールクライアントであるため、PostfixやDovecotによるメールサーバーの設定も必要となる。なお、今回は、<strong>バーチャルドメインのIMAPメールサーバー</strong>に対して設定を行っている。PostfixとDovecotの構築手順は以下を参照いただきたい。</p>
<ul>
<li><a href="https://tech-mmmm.blogspot.com/2023/11/postfixdovecotimap.html">Postfix+DovecotでバーチャルドメインのIMAPメールサーバーを構築する手順</a></li>
</ul>
<p>構築環境としては以下となる。</p>
<ul>
<li>OS : AlmaLinux 8.8</li>
<li>DB : MariaDB 10.3.35</li>
<li>Roundcube : 1.6.2</li>
<li>PHP : 7.4</li>
<li>Apache HTTP Server : 2.4.37</li>
<li>Postfix : 3.5.8</li>
<li>Dovecot : 2.3.16</li>
</ul>
<h2 id="rondcubeフィルター有効化手順">Rondcubeフィルター有効化手順</h2>
<h3 id="dovecot--pigeonholeをインストール">1. Dovecot Pigeonholeをインストール</h3>
<p>Dovecot Pigeonholeとは、メールの処理方法を定義する「Sieve」と呼ばれるスクリプト言語を用いてDovecot のメール配送処理を制御するためのソフトウェアとなる。</p>
<ul>
<li><a href="https://pigeonhole.dovecot.org/">参考:Pigeonhole</a></li>
</ul>
<p>Dovecot Pigeonholeは<code>dnf</code>コマンドにてインストールできる。</p>
<pre><code>dnf install dovecot-pigeonhole -y
</code></pre>
<h3 id="dovecot設定追加">2. Dovecot設定追加</h3>
<p>Sieveを使えるようにするため、LDA (ローカル配送エージェント) 及びLMTP (Local Mail Transfer Protocol) の設定に<code>sieve</code>を追加する。</p>
<h4 id="etcdovecotconf.d15-lda.conf"><code>/etc/dovecot/conf.d/15-lda.conf</code></h4>
<pre><code>protocol lda {
# Space separated list of plugins to load (default is global mail_plugins).
mail_plugins = $mail_plugins sieve # <- sieveを追加
}
</code></pre>
<h4 id="etcdovecotconf.d20-lmtp.conf"><code>/etc/dovecot/conf.d/20-lmtp.conf</code></h4>
<pre><code>protocol lmtp {
# Space separated list of plugins to load (default is global mail_plugins).
mail_plugins = $mail_plugins sieve # <- sieveを追加
}
</code></pre>
<p>Dovecotにて、ManageSieveと呼ばれるSieveのアップロード等を管理するための機能を有効化する。設定ファイルの前半のコメントアウトされている行をアンコメントし有効化する。</p>
<h4 id="etcdovecotconf.d20-managesieve.conf"><code>/etc/dovecot/conf.d/20-managesieve.conf</code></h4>
<pre><code># Uncomment to enable managesieve protocol:
protocols = $protocols sieve
# Service definitions
service managesieve-login {
inet_listener sieve {
port = 4190
}
inet_listener sieve_deprecated {
port = 2000
}
# Number of connections to handle before starting a new process. Typically
# the only useful values are 0 (unlimited) or 1. 1 is more secure, but 0
# is faster. <doc/wiki/LoginProcess.txt>
service_count = 1
# Number of processes to always keep waiting for more connections.
process_min_avail = 0
# If you set service_count=0, you probably need to grow this.
vsz_limit = 64M
}
</code></pre>
<p>Sieveのスクリプトファイル名は、デフォルトで<code>.dovecot.sieve</code>と隠しファイルになっているが、先頭に<code>.</code>が付いているとメールフォルダと誤認してしまう場合があるため、<code>dovecot.sieve</code>というファイル名に変更しておく。</p>
<h4 id="etcdovecotconf.d90-sieve.conf"><code>/etc/dovecot/conf.d/90-sieve.conf</code></h4>
<pre><code>plugin {
sieve = file:~/sieve;active=~/dovecot.sieve
}
</code></pre>
<p>以上が完了したら、Dovecotのサービスを再起動させる。</p>
<pre><code># systemctl restart dovecot
</code></pre>
<h3 id="postfix設定追加">3. Postfix設定追加</h3>
<p>Dovecotのローカル配送エージェントである<code>dovecot-lda</code>にメール配送をできるよう、<code>master.cf</code>に以下設定を追加する。</p>
<p>userはバーチャルメールボックスで使用するユーザー、グループである<code>vmail</code>を指定する。</p>
<h4 id="etcpostfixmaster.cf"><code>/etc/postfix/master.cf</code></h4>
<pre><code>dovecot unix - n n - - pipe
flags=DRhu user=vmail:vmail argv=/usr/libexec/dovecot/dovecot-lda -f ${sender} -d ${recipient}
</code></pre>
<p>設定した<code>dovecot-lda</code>へメールを配送するよう、<code>main.cf</code>に以下設定を追加する。</p>
<h4 id="etcpostfixmain.cf"><code>/etc/postfix/main.cf</code></h4>
<pre><code>virtual_transport = dovecot
</code></pre>
<p>以上が完了したら、Postfixのサービスを再起動させる。</p>
<pre><code>systemctl restart postfix
</code></pre>
<h3 id="roundcubeで「managesieve」のプラグインを有効化">4. Roundcubeで「ManageSieve」のプラグインを有効化</h3>
<p>以下の設定を追加する。なお、設定は即時に反映されるため、サービス等の再起動は不要となる。</p>
<h4 id="etcroundcubemailconfig.inc.php"><code>/etc/roundcubemail/config.inc.php</code></h4>
<pre><code>$config['plugins'] = array('managesieve');
</code></pre>
<h3 id="動作確認">5. 動作確認</h3>
<p>実際にRoundcubeにログインすると、「設定」画面に「フィルター」が表示されるようになっていることがわかる。</p>
<p>ここで動作確認のため、以下の通りフィルターを作成する。</p>
<ul>
<li>フィルター名 : テスト</li>
<li>規則 : 「件名」、「含む」、「テストメール」</li>
<li>操作 : 「次にメッセージを移動」、「test」フォルダ</li>
</ul>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgdM28CQk0dDvV0TLRLyemUXuSy8KPoxWMqWJ1SZekZwJaBBMeTd7y83rnTpUQ4EGBBnqZkuWNAQKxiJQI9BH6ad3VoiYofP1Hv9Gop6a-_41a7KJsUcyppzuirmF08t3y_ckaLbUNXmjPYzIfzktkh_pNteJTzMxs2_Mtj3Glde0lo5Kq0bKl-NZlwpVU/s1376/001.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="487" data-original-width="1376" height="226" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgdM28CQk0dDvV0TLRLyemUXuSy8KPoxWMqWJ1SZekZwJaBBMeTd7y83rnTpUQ4EGBBnqZkuWNAQKxiJQI9BH6ad3VoiYofP1Hv9Gop6a-_41a7KJsUcyppzuirmF08t3y_ckaLbUNXmjPYzIfzktkh_pNteJTzMxs2_Mtj3Glde0lo5Kq0bKl-NZlwpVU/w640-h226/001.png" width="640" /></a></div>
<p>実際に「これはテストメールです。」という件名のメールを送信すると、以下の通り、「test」フォルダにメールが配送されていることがわかる。</p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjGtphKRS3FkZ_I2X0fYdmqeonjOZY6NKmLjVNJzyLT6q1FwaEkXNqNHpzUhV5-LLZMvjQWbBYLytUHiT1La2EWeoyxQZYqpRLdUYhXA4SgYaFUm_nxbAVnGuiyHSsz6OqQ4U5lU7iTsCJiZ2oetxj1VuYRbKVRbeKAE45B1aWC1v6ISvXpmiKDXWJtKLg/s744/002.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="384" data-original-width="744" height="330" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjGtphKRS3FkZ_I2X0fYdmqeonjOZY6NKmLjVNJzyLT6q1FwaEkXNqNHpzUhV5-LLZMvjQWbBYLytUHiT1La2EWeoyxQZYqpRLdUYhXA4SgYaFUm_nxbAVnGuiyHSsz6OqQ4U5lU7iTsCJiZ2oetxj1VuYRbKVRbeKAE45B1aWC1v6ISvXpmiKDXWJtKLg/w640-h330/002.png" width="640" /></a></div>
<p>なお、Sieveのスクリプトファイルは、以下のように作成されていた。</p>
<pre><code># cat /var/spool/virtual/[mydomain]/[myuser]/Maildir/dovecot.sieve
require ["fileinto"];
# rule:[テスト]
if allof (header :contains "subject" "テストメール")
{
fileinto "INBOX.test";
}
</code></pre>
<p>以上で、Roundcubeにて「ManageSieve」のプラグインを有効化する手順は完了となる。</p>
tech-mmmmhttp://www.blogger.com/profile/01739191108051432575noreply@blogger.com0tag:blogger.com,1999:blog-7885523125238064555.post-36167144397352916232024-01-28T07:30:00.007+09:002024-02-01T22:23:50.988+09:00SPF、DMARC、DKIMに対応するためのDNSとPostfix (OpenDKIM)設定手順<p>Gmailは2024年2月より、1日あたり5,000件以上のメールを送信する送信元においては、<strong>SPF(エスピーエフ)、DMARC(ディーマーク)、DKIM(ディーキム)の設定が必須となる</strong>よう、セキュリティポリシーが変更される。</p>
<ul>
<li><a href="https://support.google.com/a/answer/81126?sjid=16177809414856039282-AP&visit_id=638419559513392952-508206469&rd=1#requirements-5k&zippy=%2C%E6%97%A5%E3%81%82%E3%81%9F%E3%82%8A-%E4%BB%B6%E4%BB%A5%E4%B8%8A%E3%81%AE%E3%83%A1%E3%83%BC%E3%83%AB%E3%82%92%E9%80%81%E4%BF%A1%E3%81%99%E3%82%8B%E5%A0%B4%E5%90%88%E3%81%AE%E8%A6%81%E4%BB%B6">1 日あたり 5,000 件以上のメールを送信する場合の要件</a></li>
</ul>
<p>私は自宅検証環境においてメール送受信できるPostfixのメールサーバを構築しているが、SPF以外のDMARCとDKIMの対応ができていなかった。</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiY7aRzmSXqox0DoPyxHJlkoRTCoEi3T7bHJ7CGvD9MMoh-dJZ_q5-mPRzRu-Dxw6AJV2lWPQhNhfsTve4ZTKNPHbuhHDsf3Sfav8OVzEGZNVar7rz2SjNm2BjXIrUUkTcwRBSMt5LRqj1OquFI5GK1R5qRyeOQWdDOAkg57eaQVEyWXiuSWQvk7NRdIHI/s620/%E8%A8%AD%E5%AE%9A%E5%A4%89%E6%9B%B4%E5%89%8DGmail%E7%94%BB%E9%9D%A2.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="413" data-original-width="620" height="266" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiY7aRzmSXqox0DoPyxHJlkoRTCoEi3T7bHJ7CGvD9MMoh-dJZ_q5-mPRzRu-Dxw6AJV2lWPQhNhfsTve4ZTKNPHbuhHDsf3Sfav8OVzEGZNVar7rz2SjNm2BjXIrUUkTcwRBSMt5LRqj1OquFI5GK1R5qRyeOQWdDOAkg57eaQVEyWXiuSWQvk7NRdIHI/w400-h266/%E8%A8%AD%E5%AE%9A%E5%A4%89%E6%9B%B4%E5%89%8DGmail%E7%94%BB%E9%9D%A2.png" width="400" /></a></div>
<p>そこで、本記事では、<b>DNSへレコード追加とPostfixへOpenDKIMを導入し、</b><b>SPF、DMARC、DKIMに対応した</b><b>メール送信環境を構築する手順を記載</b>する。</p>
<h2 id="環境">環境</h2>
<p>自宅検証環境の構成概要図は以下の通り。今回は、以下構成図の赤枠で示している内部のメールサーバのPostfixと、外部DNSとして利用している「お名前ドットコム」に対して設定変更を行う。</p>
<p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjK-B4ZtkJNvbQ0-4NrOCcLaSSCRFrubhHeQMFqhtIplveCc7ebAeqdvXnc5F1QPCVcvMa1dbIabJ1pUYZM8_xzhelE961EdJiYgSwhyyw7qwvBClMsUCt6SPlOv2fnosoEpQ0umXvXU-fSbl19asU4Ylgd0B-kEDiOsRk0phkhZwR0HW72P3FtL1sRGoo/s3036/%E6%A7%8B%E6%88%90%E5%9B%B3.png" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" data-original-height="2351" data-original-width="3036" height="496" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjK-B4ZtkJNvbQ0-4NrOCcLaSSCRFrubhHeQMFqhtIplveCc7ebAeqdvXnc5F1QPCVcvMa1dbIabJ1pUYZM8_xzhelE961EdJiYgSwhyyw7qwvBClMsUCt6SPlOv2fnosoEpQ0umXvXU-fSbl19asU4Ylgd0B-kEDiOsRk0phkhZwR0HW72P3FtL1sRGoo/w640-h496/%E6%A7%8B%E6%88%90%E5%9B%B3.png" width="640" /></a></p>
<p>本記事で説明に用いるドメインは<code>example.tech-mmmm.com</code>とするため、<b>各自の所有するドメインに読み替えて参照</b>いただきたい。</p>
<h2 id="spf">SPF</h2>
<p>SPFへの対応はDNSへ登録するのみで完了できる。具体的には以下のようなSPFレコード (TXTレコード)をDNSに登録する。</p>
<pre><code>example.tech-mmmm.com. 3600 IN TXT
"v=spf1 +ip4:[送信元となるメールサーバのIPアドレス] -all"
</code></pre>
<h2 id="dmarc">DMARC</h2>
<p>DMARCへの対応もSPFと同様、DNSへ登録するのみで完了できる。レコードは<code>_dmarc.[ドメイン名]</code>で登録するが、具体的には以下のようなDMARCレコード (TXTレコード)をDNSに登録する。</p>
<p><code>p=none</code>はポリシーの設定であり、今回はDMARCの結果において特に何もしない (None)という設定としている。</p>
<p><code>rua</code>と<code>ruf</code>はDMARCの判定結果のレポートを送信する自ドメインのメールアドレスを設定すればよい。設定すると、Gmailからは1日1回おおよそAM 9:00 (UTCでいうと0:00)に「Report domain: example.tech-mmmm.com Submitter: google.com」というタイトルのメールがレポートとして送られてくるようになる。</p>
<pre><code>_dmarc.example.tech-mmmm.com. 3600 IN TXT
"v=DMARC1; p=none; rua=mailto:dmarc-report@example.tech-mmmm.com; ruf=mailto:dmarc-report@example.tech-mmmm.com;"
</code></pre>
<h2 id="dkim">DKIM</h2>
<p>DKIMに関してはメール送信時に署名を付与する仕組みが必要であり、Postfixの場合はMilter (Mail Filter)として動作する<a href="http://www.opendkim.org/">OpenDKIM</a>を使用する。</p>
<p>以下に導入手順を記載する。</p>
<h3 id="opendkimインストール">1. OpenDKIMインストール</h3>
<p>EPELのリポジトリ追加後、以下をインストールする。<code>opendkim-tools</code>に鍵情報を作成するコマンドが含まれているため、併せてインストールすること。</p>
<pre><code># dnf install epel-release -y
# dnf install opendkim opendkim-tools -y
</code></pre>
<h3 id="dkim署名用の鍵を作成">2. DKIM署名用の鍵を作成</h3>
<p>DKIM署名用の鍵は、<code>opendkim-genkey</code>コマンドで行う。</p>
<p><code>-s</code>オプションでセレクタと呼ばれる任意の識別するための文字列を指定できる。今回は<code>myselector</code>と設定した。<code>-b</code>オプションは鍵の長さを設定するオプションとなり、OpenDKIMのデフォルトは1024bitとなるが、セキュリティの観点から2048bitで設定する。</p>
<pre><code># mkdir /etc/opendkim/keys/example.tech-mmmm.com
# opendkim-genkey -D /etc/opendkim/keys/example.tech-mmmm.com/ -d example.tech-mmmm.com -s myselector -b 2048
# ls -l /etc/opendkim/keys/example.tech-mmmm.com/
合計 8
-rw-------. 1 root root 887 1月 27 18:01 myselector.private
-rw-------. 1 root root 328 1月 27 18:01 myselector.txt
</code></pre>
<p>鍵情報のファイルは、ユーザー・グループを変更しておく。</p>
<pre><code># chown -R opendkim:opendkim /etc/opendkim/keys/example.tech-mmmm.com/
# ls -l /etc/opendkim/keys/example.tech-mmmm.com/
合計 8
-rw-------. 1 opendkim opendkim 887 1月 27 18:01 myselector.private
-rw-------. 1 opendkim opendkim 328 1月 27 18:01 myselector.txt
</code></pre>
<h3 id="設定ファイル修正">3. 設定ファイル修正</h3>
<p>OpenDKIMの設定ファイルである<code>opendkim.conf</code>を以下の通り修正する。</p>
<pre><code># vi /etc/opendkim.conf
Mode sv <span> </span># vからsvに変更
Socket inet:8891@localhost <span> </span># アンコメント (UNIXドメインソケットからinetソケットに変更)
#Socket local:/run/opendkim/opendkim.sock <span> </span># コメントアウト
Selector myselector <span> </span># defaultから変更
KeyTable /etc/opendkim/KeyTable <span> </span># アンコメント
SigningTable refile:/etc/opendkim/SigningTable <span> </span># アンコメント
ExternalIgnoreList refile:/etc/opendkim/TrustedHosts<span> </span># アンコメント
InternalHosts refile:/etc/opendkim/TrustedHosts <span> </span># アンコメント
</code></pre>
<p>セレクタとドメインのに対して使用する鍵情報を紐づける<code>KeyTable</code>ファイルを以下の通り記載する。</p>
<pre><code># vi /etc/opendkim/KeyTable
myselector._domainkey.example.tech-mmmm.com example.tech-mmmm.com:myselector:/etc/opendkim/keys/myselector.private
</code></pre>
<p>署名する際のメールのドメインと使用する鍵情報を紐づける<code>SigningTable</code>ファイルを以下の通り記載する。</p>
<pre><code># vi /etc/opendkim/SigningTable
*@example.tech-mmmm.com myselector._domainkey.example.tech-mmmm.com
</code></pre>
<p>OpenDKIMが信頼できるホストとして認識するホストやネットワークを指定する。今回は内部環境となるので、<code>0.0.0.0/0</code>で指定する。</p>
<pre><code># vi /etc/opendkim/TrustedHosts
0.0.0.0/0
</code></pre>
<h3 id="opendkimサービスを起動">4. OpenDKIMサービスを起動</h3>
<p>設定完了後、OpenDKIMのサービスを起動させる。</p>
<pre><code># systemctl start opendkim
# systemctl enable opendkim
</code></pre>
<p>起動するとポート8891番でLISTENしているかどうか確認しておく。</p>
<pre><code># ss -nl | grep 8891
tcp LISTEN 0 128 127.0.0.1:8891 0.0.0.0:*
</code></pre>
<h3 id="postfixの設定修正">5. Postfixの設定修正</h3>
<p>OpenDKIMをMilterとして指定するため、以下3行を追加する。</p>
<pre><code># vi /etc/postfix/main.cf
smtpd_milters = inet:127.0.0.1:8891
non_smtpd_milters = $smtpd_milters
milter_default_action = accept
</code></pre>
<p>設定完了後、Postfixを再起動しておく。</p>
<pre><code># systemctl restart postfix
</code></pre>
<h3 id="dns設定">6. DNS設定</h3>
<p>DKIMはDNSの登録された公開鍵情報を用いて署名の検証を行うため、DNSへレコードの追加が必要となる。レコードは<code>[セレクタ名]._domainkey.[ドメイン名]</code>で登録する。レコードの内容は鍵を生成した際に作成される、<code>/etc/opendkim/keys/example.tech-mmmm.com/myselector.txt</code>のファイルに記載されているで、このまま登録を行えば問題ない。</p>
<pre><code># cat /etc/opendkim/keys/example.tech-mmmm.com/myselector.txt
myselector._domainkey IN TXT ( "v=DKIM1; k=rsa; "
"p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCyLeUjkqVc712NhH1/20UMGW4rxg4F4sQilrauxt5mWPEbu342y+Px+OD4oVZ1yeF9NAAAgExIJBwl854p1bn87rVgam9J/3mYICCD5GhbBy6MEFODgMZXcSvJ8Q2g7S1Y0mro95mI2p+8WtPfxjUTzERemcduNa3eZu7+i1I1GwIDAQAB" ) ; ----- DKIM key myselector for example.tech-mmmm.com
</code></pre>
<p>上記の通りDNSに登録を行う。</p>
<pre><code>myselector._domainkey.example.tech-mmmm.com. 3600 IN TXT
"v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCyLeUjkqVc712NhH1/20UMGW4rxg4F4sQilrauxt5mWPEbu342y+Px+OD4oVZ1yeF9NAAAgExIJBwl854p1bn87rVgam9J/3mYICCD5GhbBy6MEFODgMZXcSvJ8Q2g7S1Y0mro95mI2p+8WtPfxjUTzERemcduNa3eZu7+i1I1GwIDAQAB"
</code></pre>
<h2 id="動作確認">動作確認</h2>
<p>実際にメールを送信した際のGmailにおける受信結果が以下となる。SPF、DKIM、DMARCがすべてPASSしていることがわかる。</p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiDX3sPMNyxN8_umYpSY0_XCDmDaLvj5OQ1cRZ8sW5K-NrVZFtWcUbOlb2YsIsBK0MJ5fIUajxSpbz1rNgsiwt5xU0FMY5kskN6s6NvCRq0zcS0gqIkWOmieiREJeA7AkrucRp7cs9mYCxR3DUdi2O_TvVY_VIP0JN12jJUKN-s-y9jRu2NzSpXe4CXHPA/s668/016.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="448" data-original-width="668" height="269" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiDX3sPMNyxN8_umYpSY0_XCDmDaLvj5OQ1cRZ8sW5K-NrVZFtWcUbOlb2YsIsBK0MJ5fIUajxSpbz1rNgsiwt5xU0FMY5kskN6s6NvCRq0zcS0gqIkWOmieiREJeA7AkrucRp7cs9mYCxR3DUdi2O_TvVY_VIP0JN12jJUKN-s-y9jRu2NzSpXe4CXHPA/w400-h269/016.png" width="400" /></a></div>
<p>以上で、DNSへレコード追加とPostfixへOpenDKIMを導入し、SPF、DMARC、DKIMに対応したメール送信環境を構築する手順は完了となる。</p>
tech-mmmmhttp://www.blogger.com/profile/01739191108051432575noreply@blogger.com0tag:blogger.com,1999:blog-7885523125238064555.post-87562801742426759992024-01-21T18:17:00.002+09:002024-01-21T18:20:52.590+09:00Raspberry Pi OSなどのDebian系OSのviで、方向キーによる移動やバックスペースを使えるようにするRaspberry Pi OSなどのDebianベースのOSにおいてviを使う際に、入力モード(i または aを押して文字入力ができる状態)にした際に方向キーで移動しようとすると、ABCDの文字が入力されてしまう。<br />
<br />
方向キーと文字の関係は以下の通り。<br />
<pre><code> A
|
D -+- C
|
B
</code></pre>
とても不便なので、<b>viで方向キーを用いても通常通りカーソルを移動できるように設定する。併せてviでバックスペースも正常に使用できるように対処</b>する。<h2 style="text-align: left;">設定手順</h2><div>各ユーザーのホームディレクトリに.vimrcというファイルを作成し、以下2行の設定を書き込んでやればよい。<br />
<pre><code>set nocompatible
set backspace=indent,eol,start
</code></pre>ワンライナーで設定したい場合は以下の通り実施する。すでに.vimrcがある可能性を考慮して、追記でリダイレクトしている。<br />
<pre><code>$ echo -e "set nocompatible\nset backspace=indent,eol,start" >> ~/.vimrc
$ cat ~/.vimrc
set nocompatible
set backspace=indent,eol,start
</code></pre>
これだけで、特に再ログイン等も不要で、次回vi実行時から設定が反映され、入力モードであっても方向キーが使えるようになる。<br /></div><div><div><h2>参考</h2></div><div><ul><li><a href="https://vimhelp.org/options.txt.html#%27backspace%27">Vim: options.txt</a></li></ul></div></div><h2 style="text-align: left;">更新履歴</h2><div><ul style="text-align: left;"><li>2018/3/26 新規作成</li><li>2024/1/21 補足情報を追記</li></ul></div>tech-mmmmhttp://www.blogger.com/profile/01739191108051432575noreply@blogger.com0tag:blogger.com,1999:blog-7885523125238064555.post-19688201647513690562024-01-20T16:34:00.000+09:002024-01-20T16:34:37.482+09:00Zabbix APIを使って未クローズの障害イベントをクローズする<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgoGR1qQcGYvcheeJEaQao1LAfDNVKDI5Y3Zu6HBJyZ5YkUEQFym6YAINX6CiP-a1JpYEjehQ_BDWhEhZKdD6zlB3J8kf24G8Qs3Kl6aYcu0EsbVuBFZOhbUOC4ei6_MEma4oI0RQ25bTo/s625/eye023.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="357" data-original-width="625" height="364" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgoGR1qQcGYvcheeJEaQao1LAfDNVKDI5Y3Zu6HBJyZ5YkUEQFym6YAINX6CiP-a1JpYEjehQ_BDWhEhZKdD6zlB3J8kf24G8Qs3Kl6aYcu0EsbVuBFZOhbUOC4ei6_MEma4oI0RQ25bTo/w640-h364/eye023.png" width="640" /></a></div><p>Zabbixではトリガーによって検知した障害は、復旧条件を満たさなければクローズされることはなく、いつまでも障害として残り続けてしまう。</p>
<p>Zabbix 4.0以降では、管理画面から手動による障害のクローズができるようになったため、復旧条件の記載が難しいログ監視やSNMP Trap監視などにおいても、クローズができるようになりかなり便利になった。</p>
<p>とはいえ、大量の監視対象がある環境においては、障害のクローズを手作業で実施すること自体が負荷となるケースが存在すると考えられるため、今回は<strong>Zabbix APIを使って未クローズの障害イベントを一気にクローズする手順</strong>を検証した。</p>
<h2 id="環境">環境</h2>
<p>環境は以下の通りZabbix 5.0を使用している。ただし、Zabbix 4.0以降でも利用できることを確認するため、Zabbix APIのマニュアルはZabbix 4.0のものを確認して検証を行った。</p>
<ul>
<li>OS : CentOS 8.1</li>
<li>Zabbix : 5.0.8</li>
<li>APIのURL : <code>http://192.168.11.24/zabbix/api_jsonrpc.php</code></li>
</ul>
<p>Zabbix APIを使用する際に、<code>jq</code>コマンドが必要となるため、事前にインストールをしておく。<code>jq</code>コマンドは、Zabbix APIやREST APIなどで利用されているJSON形式のデータを整形して出力したり、必要なデータのみ抽出するのに利用するコマンドとなる。</p>
<pre><code># dnf install epel-release
# dnf install jq
</code></pre>
<h2 id="手順">手順</h2>
<p>Zabbix APIを実行する際に送信するJSON形式のデータは、以下構文となる。</p>
<pre><code>{
"jsonrpc": "2.0",
"method": "メソッド名",
"params": {
"パラメータ1 Key": "パラメータ1 Value",
"パラメータ2 Key": "パラメータ2 Value",
...
},
"auth": "Zabbix認証トークン",
"id": 任意の数字
}
</code></pre>
<p>以降の手順では、<strong>上記構文の送信データを作成したのち、<code>curl</code>コマンドでそのデータを送信してAPIを実行する</strong>、という流れとなる。</p><p><span face="Arial, Tahoma, Helvetica, FreeSans, sans-serif" style="background-color: white; color: #222222; font-size: 15.4px;">また、Zabbix APIのURLやヘッダ情報などは、毎回同一となることから、あらかじめ変数として利用できるようにしておこう。</span></p>
<pre><code># header='Content-Type:application/json-rpc'
# apiurl='http://192.168.11.24/zabbix/api_jsonrpc.php'
</code></pre>
<h3 id="zabbix-apiの認証トークンを取得">1. Zabbix APIの認証トークンを取得</h3>
<p>Zabbix APIの実行は、認証トークンが必要となる。認証トークンは、<code>user.login</code>メソッドで取得できる。Zabbixの管理者権限を持つユーザとパスワードを指定して、以下のようにAPIを実行するためのデータを作成する。</p>
<pre><code># json='{"jsonrpc": "2.0","method": "user.login","params": {"user": "Admin","password": "XXXXXXXX"},"id": 1,"auth": null}'
# echo $json | jq
{
"jsonrpc": "2.0",
"method": "user.login",
"params": {
"user": "Admin",
"password": "XXXXXXXX"
},
"id": 1,
"auth": null
}
</code></pre>
<p>認証トークンは、以降の作業で常に指定して利用することから、実行結果を変数<code>$zbxauth</code>に代入しておく。</p>
<pre><code># zbxauth=$(curl -sS -X POST -H "${header}" -d "${json}" ${apiurl} | jq -r ".result")
# echo $zbxauth
e2519a6fbc680a87affc8382b65cdcb7
</code></pre>
<h3 id="未クローズの障害イベントを取得">2. 未クローズの障害イベントを取得</h3>
<p>障害イベントのクローズには、<code>eventid</code>が必要となる。<code>problem.get</code>メソッドを使うことで一覧として取得できるので、以下の通り送信データを作成する。</p>
<pre><code># json='{"jsonrpc": "2.0","method": "problem.get","params": {"output": "eventid"},"id": 3,"auth": "'$zbxauth'"}'
# echo $json | jq
{
"jsonrpc": "2.0",
"method": "problem.get",
"params": {
"output": "eventid"
},
"id": 3,
"auth": "e2519a6fbc680a87affc8382b65cdcb7"
}
</code></pre>
<p>取得した<code>eventid</code>は、次の手順で配列として利用できるようにするため、<code>jq</code>コマンドを使って出力結果を整形して変数<code>$eventids</code>に格納する。以下コマンドの実行例では、6件の障害イベントが対象となる。</p>
<pre><code># eventids=$(curl -sS -X POST -H "${header}" -d "${json}" ${apiurl} | jq -c '[ .result[].eventid ]')
# echo $eventids
["34308","50073","50875","50876","50877","50954"]
</code></pre>
<h3 id="障害イベントを手動クローズ">3. 障害イベントを手動クローズ</h3>
<p>イベントに対する捜査は<code>event.acknowledge</code>メソッドを使う。<code>event.acknowledge</code>メソッドでは、イベントに対して実行する処理を<code>action</code>にて指定するが、その際に指定できる値は以下の通りとなる。</p>
<ul>
<li>1 - close problem;</li>
<li>2 - acknowledge event;</li>
<li>4 - add message;</li>
<li>8 - change severity.</li>
</ul>
<p>上記は組み合わせることが可能であり、今回は「1 : 障害のクローズ」と「4 : メッセージ追加」の2つを同時に実行するため、<code>action</code>を1 + 4 = 5で指定する。</p>
<pre><code># json='{"jsonrpc": "2.0", "method": "event.acknowledge", "params": {"eventids": '$eventids', "action": 5, "message": "Closed problem by API"}, "auth": "'$zbxauth'", "id": 1}'
# echo $json | jq
{
"jsonrpc": "2.0",
"method": "event.acknowledge",
"params": {
"eventids": [
"34308",
"50073",
"50875",
"50876",
"50877",
"50954"
],
"action": 5,
"message": "Closed problem by API"
},
"auth": "e2519a6fbc680a87affc8382b65cdcb7",
"id": 1
}
</code></pre>
<p>障害イベントのクローズ前に、GUI上でも障害一覧を確認しておく。1件はホストを無効化しているため障害が表示されていないが、GUI上では5件の障害が表示されている。後ほど、API実行後に赤枠で示したアラートがクローズされることを確認する。</p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhLazYGbqRB8d09RMpbFpWwZHL35XCgvf__83fyc6ny9vR6Dhx60a1hv_nNepys2p9SBG95Gj8m40-K4PusvNG_NxoBwFEvGrm9V1DCwgmDg8mFGfHoqBzE2EFCsX2OuVkuU32PSJ7E5dE/s1232/218.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="306" data-original-width="1232" height="158" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhLazYGbqRB8d09RMpbFpWwZHL35XCgvf__83fyc6ny9vR6Dhx60a1hv_nNepys2p9SBG95Gj8m40-K4PusvNG_NxoBwFEvGrm9V1DCwgmDg8mFGfHoqBzE2EFCsX2OuVkuU32PSJ7E5dE/w640-h158/218.png" width="640" /></a></div>
<p><code>curl</code>にてAPIを実行する。<code>result</code>に処理を実行したイベントIDの一覧が表示されればOKとなる。</p>
<pre><code># curl -sS -X POST -H "${header}" -d "${json}" ${apiurl} | jq
{
"jsonrpc": "2.0",
"result": {
"eventids": [
34308,
50073,
50875,
50876,
50877,
50954
]
},
"id": 1
}
</code></pre>
<p>GUI上にて再度障害一覧を確認すると、すべての障害がクローズされ、一覧から消えていることが確認できた。</p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh6ZYfsDR9nJlFv0iNdg3YlZkobNa9HMEqkMxiDbclgizSMhPiRf2Kza7X8P7bwbseh2iyWGP-s2fHR27JQiOhdwdtkJInHf-sG3OkUI-4lOSTpRFo1O0VjPEQ5N10Hy_OXzqcJbO_4Pf8/s1720/219.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="611" data-original-width="1720" height="228" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh6ZYfsDR9nJlFv0iNdg3YlZkobNa9HMEqkMxiDbclgizSMhPiRf2Kza7X8P7bwbseh2iyWGP-s2fHR27JQiOhdwdtkJInHf-sG3OkUI-4lOSTpRFo1O0VjPEQ5N10Hy_OXzqcJbO_4Pf8/w640-h228/219.png" width="640" /></a></div><p>また、クローズされたイベントを確認すると、<b>APIで指定した「Closed problem by API」のメッセージとともに、ステータスが「解決済」になっている</b>ことが確認できた。</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhapjlHAA7YQM-zQJOYJhEh_1QuItoqMLT8LaLvu8Y71FnojH5RKtgrwuqoTeX8i_4nJxwMPDhfgM-bUbP_Jp5pQbLvtPcYGvLAuEDjpcQkeMO1LyZrwEhK-jIlFqNItTbd1zjAUWK2TF_xK-qCf5pin3Yp0h5guFjIRfgzXOVK2c9pGhVWhmEdRlem/s1727/226.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="707" data-original-width="1727" height="262" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhapjlHAA7YQM-zQJOYJhEh_1QuItoqMLT8LaLvu8Y71FnojH5RKtgrwuqoTeX8i_4nJxwMPDhfgM-bUbP_Jp5pQbLvtPcYGvLAuEDjpcQkeMO1LyZrwEhK-jIlFqNItTbd1zjAUWK2TF_xK-qCf5pin3Yp0h5guFjIRfgzXOVK2c9pGhVWhmEdRlem/w640-h262/226.png" width="640" /></a></div>
<h3 id="zabbix-apiの認証トークンを削除">4. Zabbix APIの認証トークンを削除</h3>
<p>最後に認証トークンを削除するため、<code>user.logout</code>メソッドを使用する。</p>
<pre><code># json='{"jsonrpc": "2.0","method": "user.logout","params": [],"id": 4,"auth": "'$zbxauth'"}'
# echo $json | jq
{
"jsonrpc": "2.0",
"method": "user.logout",
"params": [],
"id": 4,
"auth": "e2519a6fbc680a87affc8382b65cdcb7"
}
</code></pre>
<p><code>curl</code>にてAPIを実行し、<code>result</code>が<code>true</code>であれば、認証トークンの削除が正常に実施されている。</p>
<pre><code># curl -sS -X POST -H "${header}" -d "${json}" ${apiurl} | jq
{
"jsonrpc": "2.0",
"result": true,
"id": 4
}
</code></pre>
<h2 id="環境">スクリプト化してみる</h2>
<p style="font-size: medium; font-weight: 400;">クローズ処理を定期的に実行できるよう<code>close_zabbix_problem.sh</code>という名前のスクリプトを作成し、cronに登録して定期的に古い障害イベントをクローズできるようにしてみた。</p><p style="font-size: medium; font-weight: 400;">7日前の未分類、情報、警告ステータスのイベントをクローズする処理となり、クローズする対象を限定するため、イベントID取得時に、<code>time_till</code>や<code>severities</code>といったパラメータを指定している。</p>
<pre><code>#!/bin/bash
# クローズ対象の日付
clode_date=$(date +%s --date '7 day ago')
close_message="Closed problem by API"
# Zabbix APIログイン
header='Content-Type:application/json-rpc'
apiurl='http://192.168.11.24/zabbix/api_jsonrpc.php'
json='{"jsonrpc": "2.0","method": "user.login","params": {"user": "Admin","password": "XXXXXXXX"},"id": 1,"auth": null}'
zbxauth=$(curl -sS -X POST -H "${header}" -d "${json}" ${apiurl} | jq -r ".result")
# イベント一覧(未解決の障害、指定日以前のもの、未分類・情報・警告イベント)を取得
json='{"jsonrpc": "2.0","method": "problem.get","params": {"output": "eventid","time_till": '${clode_date}',"severities": [0,1,2]},"auth": "'${zbxauth}'","id": 1}'
eventids=$(curl -sS -X POST -H "${header}" -d "${json}" ${apiurl} | jq -r '.result[].eventid ' | tr '\n' ' ')
# Zabbix APIでイベントにメッセージ追加しクローズ
for eventid in ${eventids}; do
json='{"jsonrpc": "2.0","method": "event.acknowledge","params": {"eventids": '${eventid}',"action": 5,"message": "'${close_message}'"},"auth": "'${zbxauth}'","id": 1}'
curl -sS -X POST -H "${header}" -d "${json}" ${apiurl} | jq
done
# Zabbix APIログオフ
json='{"jsonrpc": "2.0","method": "user.logout","params": [],"id": 4,"auth": "'$zbxauth'"}'
curl -sS -X POST -H "${header}" -d "${json}" ${apiurl} | jq
exit 0</code></pre>
<h2 id="参考">参考</h2>
<ul>
<li><a href="https://tech-mmmm.blogspot.com/2019/02/zabbix-api.html">Zabbix API入門</a></li>
<li><a href="https://blog.zabbix.com/close-problem-automatically-via-zabbix-api/12461/">Close problem automatically via Zabbix API – Zabbix Blog</a></li>
<li><a href="https://www.zabbix.com/documentation/4.0/manual/api/reference/problem/get">problem.get [Zabbix Documentation 4.0]</a></li>
<li><a href="https://www.zabbix.com/documentation/4.0/manual/api/reference/event/acknowledge">event.acknowledge [Zabbix Documentation 4.0]</a></li>
</ul>
<h2 id="更新履歴">更新履歴</h2><div><ul style="text-align: left;"><li>2021/2/17 新規作成</li><li>2024/1/20 クローズ処理のスクリプト化の記載を追記</li></ul></div>
tech-mmmmhttp://www.blogger.com/profile/01739191108051432575noreply@blogger.com0tag:blogger.com,1999:blog-7885523125238064555.post-27374952047630115432023-12-30T09:05:00.010+09:002023-12-30T14:49:55.001+09:00Kickstartを使ってRHEL 8やRHEL 9を自動インストールする<p>自宅で検証をする際に、Red Hat Enterprise Linux (RHEL) やCentOS、最近ではRocky LinuxやAlmaLinuxなど、RHEL系のディストリビューションを利用することが多く、頻繁にインストール作業を手作業で行っていた。</p>
<p>慣れてしまえばそこまで時間を要するものではないので、GUIを使ってせっせとインストール作業をしていたが、もっと効率よくインストールできるよう、<strong>Kickstart (キックスタート) を使ってインストールの自動化をする</strong>ことにした。</p>
<h2 id="環境">環境</h2>
<p>Kickstartの検証はESXi上に構築したRHEL 8及びRHEL9で実施した。検証完了後に同じKickstartファイルを使って、他ディストリビューションでの動作確認もしており、<strong>Rocky Linux、AlmaLinuxでもKickstartによる自動インストールが動作する</strong>ことを確認している。</p><p>以下に確認したディストリビューションの一覧を記載する。</p>
<ul>
<li>RHEL 8.3</li>
<li>Rocky Linux 8.3</li>
<li>AlmaLinux 8.3</li>
<li>RHEL 9.2</li>
</ul>
<h2 id="手順">手順</h2>
<h3 id="kickstartファイル-ks.cfg-を作成">1. Kickstartファイル (<code>ks.cfg</code>) を作成</h3>
<p>Kickstartは、<strong>インストール情報を定義したKickstartファイルと呼ばれるファイルを読み込ませることで自動インストールを実現する</strong>。このファイルは通常<code>ks.cfg</code>というファイル名で作成をするのが一般的となるが、ファイル名は任意で設定して問題ない。</p>
<p>Kickstartファイルは、インストール時に各種設定を定義するためのコマンドやオプションが用意されている。詳細は<a href="https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/9/html-single/performing_an_advanced_rhel_9_installation/index#performing_an_automated_installation_using_kickstart">公式マニュアル</a>を参照いただきたいが、最低限必要となるコマンドについては、以下表にて説明する。</p><p>なお、<b>RHEL 8とRHEL 9で細かいところで設定方法が異なる個所があるため注意</b>すること。</p>
<table>
<thead>
<tr>
<th style="width: 25%;">設定項目</th>
<th style="width: 20%;">設定コマンド</th>
<th style="width: 65%;">説明</th>
</tr>
</thead>
<tbody>
<tr>
<td>インストールモード</td>
<td><code>text</code></td>
<td>インストールをGUIベース (<code>graphical</code>) にするか、CLIベース (<code>text</code>) にするかの設定。</td>
</tr>
<tr>
<td>利用規約 (EULA) への同意</td>
<td><code>eula --agreed</code></td>
<td>利用規約への同意を自動で行う設定。</td>
</tr>
<tr>
<td>リポジトリ</td>
<td><code>repo</code></td>
<td>インストールに使用するリポジトリのパスを指定。インストールイメージに応じて変更が必要。</td>
</tr>
<tr>
<td>パッケージ</td>
<td><code>%packages</code>~<code>%end</code></td>
<td>必要なパッケージを指定。最小インストールの場合は、<code>@^minimal-environment</code>を指定。</td>
</tr>
<tr>
<td>インストール後のスクリプト実行</td>
<td><code>%post</code>~<code>%end</code></td>
<td>インストール後の処理として実行するコマンドを記載する。インストール中の文字化けを防止するため、このタイミングで言語設定を<code>ja_JP.UTF-8</code>へ変更をしている。</td>
</tr>
<tr>
<td>キーボードレイアウト</td>
<td><code>keyboard</code></td>
<td>キーボードレイアウトを指定。</td>
</tr>
<tr>
<td>言語設定</td>
<td><code>lang</code></td>
<td>システムの言語設定。ここで<code>ja_JP.UTF-8</code>を選ぶと、インストールは進むものの画面表示が文字化けした状態となるため、あえて<code>en_US.UTF-8</code>を選択している。</td>
</tr>
<tr>
<td>ネットワーク</td>
<td><code>network</code></td>
<td>ホスト名やIPアドレスなどの設定。本設定を省略すると、DHCPによる設定が反映される。</td>
</tr>
<tr>
<td>インストールタイプ</td>
<td><code>cdrom</code></td>
<td>ISOイメージからのインストールを設定。</td>
</tr>
<tr>
<td>初期セットアップ</td>
<td><code>firstboot</code></td>
<td>初期セットアップの処理を実行するかどうか。初期インストールであれば、有効にしておけば問題ない。</td>
</tr>
<tr>
<td>無視するディスク</td>
<td><code>ignoredisk</code></td>
<td><code>--drives</code>オプションにてインストールに関係ないディスクを無視するよう設定する。逆に特定のディスクのみを指定する場合は、<code>--only-use</code>を使用する。仮想環境の場合は、<code>sda</code>のみ指定しておけば問題ない。</td>
</tr>
<tr>
<td>自動パーティション</td>
<td><code>autopart</code></td>
<td>自動的にパーティションを設定する際に指定。</td>
</tr>
<tr>
<td>パーティション初期化</td>
<td><code>clearpart</code></td>
<td>パーティションの初期化動作を指定。<code>--initlabel</code>オプションにて、対象ディスク (<code>ignoredisk</code>で指定したディスク) をすべてフォーマットする。<code>--none</code>はもしパーティションが存在する場合は削除しないためのオプション。</td>
</tr>
<tr>
<td>タイムゾーン</td>
<td><code>timezone</code></td>
<td>タイムゾーンを設定する。日本にする場合は<code>Asia/Tokyo</code>を選択する。RHEL 8の場合はここでNTPサーバを指定できる。その場合は、<code>--ntpservers</code>にて指定する。また、<b>ハードウェアクロックをUTCの時刻とみなす際のオプションがRHEL 8は<code>--isUtc</code>、RHEL 9は<code>--utc</code>と異なるため注意</b>する。</td>
</tr>
<tr>
<td>タイムソース</td>
<td><code>timesource</code></td>
<td>RHEL 9の場合は本設定項目にてタイムソースとするNTPサーバを指定する。<code>--ntp-server</code>を用いて指定する。</td>
</tr>
<tr>
<td>rootパスワード</td>
<td><code>rootpw</code></td>
<td>平文 (<code>--plaintext</code>) またはハッシュ化 (<code>--iscrypted</code>) した文字列でパスワードを指定できる。ハッシュ化したパスワードは、インストール済みの環境の<code>/etc/shadow</code>から抽出すると楽。<br />RHEL 9以降はデフォルトでrootログインが禁止されるため、もしrootログインを許可したい場合は、<code>--allow-ssh</code>オプション(RHEL 9.1以降で使用可能)を付与する(RHEL 8の場合は特に指定しなくてもデフォルトでrootにてログイン可能)。</td>
</tr>
<tr>
<td>SELinux</td>
<td><code>selinux</code></td>
<td>SELinuxの有効化、無効化を設定。</td>
</tr>
<tr>
<td>ファイアウォール</td>
<td><code>firewall</code></td>
<td>firewalldの有効化、無効化を設定。</td>
</tr>
<tr>
<td>インストール後の動作</td>
<td><code>reboot</code></td>
<td>インストール後に自動で再起動かける場合に指定。同時にDVDを取り出したい場合は、<code>--eject</code>を付与する。</td>
</tr>
<tr>
<td>kdump</td>
<td><code>%addon com_redhat_kdump</code>~<code>%end</code></td>
<td>kdumpの設定。</td>
</tr>
<tr>
<td>パスワードポリシー</td>
<td><code>%anaconda</code>~<code>%end</code></td>
<td>パスワードの最小文字列などのパスワードポリシーの設定。<b>RHEL 9からは本設定項目は非推奨</b>となっている。</td>
</tr>
</tbody>
</table><p>以下に私が実際に使用しているKickstartファイルを例として記載する。OSインストールイメージがDVD版の場合とMinimal版の場合で変更を加える箇所があり、具体的には以下2点となる。</p>
<ul>
<li>レポジトリのパス</li>
<li><code>open-vm-tools</code>のインストール方式 (Minimalのイメージには<code>open-vm-tools</code>が含まれないため、<code>dnf</code>を使ってインストールする必要がある)</li>
</ul>
<h4 id="▼【RHEL 8】osインストールイメージがdvdの場合">▼【RHEL 8】OSインストールイメージがDVDの場合</h4>
<pre><code>#version=RHEL8
# Use text install
text
# Agree EULA
eula --agreed
# Package
repo --name="AppStream" --baseurl=file:///run/install/sources/mount-0000-cdrom/AppStream
%packages
@^minimal-environment
@guest-agents
kexec-tools
%end
# Run post script
%post --logfile=/root/ks-post.log
echo 'LANG="ja_JP.UTF-8"' > /etc/locale.conf ; cat /etc/locale.conf
%end
# Keyboard layouts
keyboard --xlayouts='jp'
# System language
lang en_US.UTF-8 --addsupport=ja_JP.UTF-8
# Network information
network --bootproto=static --device=ens192 --gateway=192.168.11.31 --ip=192.168.11.192 --nameserver=192.168.11.61,192.168.11.62 --netmask=255.255.255.0 --noipv6 --activate
network --hostname=localhost.localdomain
# Use CDROM installation media
cdrom
# Run the Setup Agent on first boot
firstboot --enable
ignoredisk --only-use=sda
autopart
# Partition clearing information
clearpart --none --initlabel
# System timezone
timezone Asia/Tokyo --isUtc --ntpservers=192.168.33.23
# Root password
rootpw --plaintext XXXXXXXX
#rootpw --iscrypted XXXX~(省略)~XXXX
# Disable SELinux
selinux --disabled
# Disable firewalld
firewall --disabled
# Reboot after installation
reboot
%addon com_redhat_kdump --enable --reserve-mb='auto'
%end
%anaconda
pwpolicy root --minlen=6 --minquality=1 --notstrict --nochanges --notempty
pwpolicy user --minlen=6 --minquality=1 --notstrict --nochanges --emptyok
pwpolicy luks --minlen=6 --minquality=1 --notstrict --nochanges --notempty
%end
</code></pre>
<h4 id="▼【RHEL 8】osインストールイメージがminimalの場合">▼【RHEL 8】OSインストールイメージがMinimalの場合</h4>
<pre><code>#version=RHEL8
# Use text install
text
# Agree EULA
eula --agreed
# Package
repo --name="Minimal" --baseurl=file:///run/install/sources/mount-0000-cdrom/Minimal
%packages
@^minimal-environment
kexec-tools
%end
# Run post script
%post --logfile=/root/ks-post.log
echo 'LANG="ja_JP.UTF-8"' > /etc/locale.conf ; cat /etc/locale.conf
export http_proxy=http://192.168.33.23:8080
export https_proxy=http://192.168.33.23:8080
dnf install open-vm-tools -y
%end
# Keyboard layouts
keyboard --xlayouts='jp'
# System language
lang en_US.UTF-8 --addsupport=ja_JP.UTF-8
# Network information
network --bootproto=static --device=ens192 --gateway=192.168.11.31 --ip=192.168.11.192 --nameserver=192.168.11.61,192.168.11.62 --netmask=255.255.255.0 --noipv6 --activate
network --hostname=localhost.localdomain
# Use CDROM installation media
cdrom
# Run the Setup Agent on first boot
firstboot --enable
ignoredisk --only-use=sda
autopart
# Partition clearing information
clearpart --none --initlabel
# System timezone
timezone Asia/Tokyo --isUtc --ntpservers=192.168.33.23
# Root password
rootpw --plaintext XXXXXXXX
#rootpw --iscrypted XXXX~(省略)~XXXX
# Disable SELinux
selinux --disabled
# Disable firewalld
firewall --disabled
# Reboot after installation
reboot
%addon com_redhat_kdump --enable --reserve-mb='auto'
%end
%anaconda
pwpolicy root --minlen=6 --minquality=1 --notstrict --nochanges --notempty
pwpolicy user --minlen=6 --minquality=1 --notstrict --nochanges --emptyok
pwpolicy luks --minlen=6 --minquality=1 --notstrict --nochanges --notempty
%end
</code></pre>
<h4 id="▼【RHEL 9】osインストールイメージがdvdの場合">▼【RHEL 9】OSインストールイメージがDVDの場合</h4>
<pre><code>#version=RHEL9
# Use text install
text
# Agree EULA
eula --agreed
# Package
repo --name="AppStream" --baseurl=file:///run/install/sources/mount-0000-cdrom/AppStream
%packages
@^minimal-environment
@guest-agents
%end
# Run post script
%post --logfile=/root/ks-post.log
echo 'LANG="ja_JP.UTF-8"' > /etc/locale.conf ; cat /etc/locale.conf
%end
# Keyboard layouts
keyboard --xlayouts='jp'
# System language
#lang ja_JP.UTF-8
lang en_US.UTF-8 --addsupport=ja_JP.UTF-8
# Network information
#network --bootproto=static --device=ens192 --gateway=192.168.11.31 --ip=192.168.11.192 --nameserver=192.168.11.61,192.168.11.62 --netmask=255.255.255.0 --noipv6 --activate
network --hostname=localhost.localdomain
# Use CDROM installation media
cdrom
# Run the Setup Agent on first boot
firstboot --enable
ignoredisk --only-use=sda
autopart
# Partition clearing information
clearpart --none --initlabel
# System timezone
timezone Asia/Tokyo --utc
timesource --ntp-server 192.168.33.23
# Root password
#rootpw --plaintext --allow-ssh XXXXXXXX
rootpw --iscrypted --allow-ssh XXXX~(省略)~XXXX
# Disable SELinux
selinux --disabled
# Disable firewalld
firewall --disabled
# Reboot after installation
reboot
%addon com_redhat_kdump --enable --reserve-mb='auto'
%end
</code></pre>
<h3 id="nfsサーバにkickstartファイルを配置">2. NFSサーバにKickstartファイルを配置</h3>
<p>作成したKickstartファイルは、OSインストール時に読み込ませる必要がある。いくつか方式はあるが、今回はNFSサーバにKickstartファイルを配置して、ネットワーク経由で読み込みさせることにする。</p>
<p>NFSサーバの構築は本題とは関係がないため割愛するが、今回はQNAP NASをNFSサーバとして使用することにした。配置パスは以下となる。</p>
<pre><code>nfs:192.168.11.13:/Public2/ks/ks.cfg
</code></pre>
<h3 id="osインストールメディアで起動">3. OSインストールメディアで起動</h3>
<p>通常通りOSインストールメディアにて起動し、最初の画面にて「Install Red Hat Enterprise Linux 8.3」を選択したのち、「e」を押し、インストールパラメータを指定する画面に遷移する。</p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgqLJsiOF8XpsacxHlf-LOCMqLMDaHWFrUHMX9MjzOWqTSAC4dBhX2DEIgBXRJv2_WO_xhpVR4gvyaUG6HLwW5WP_atjb9-q-QFLhLWD2-ogX2gPoqxPahyew-kgNJtNgLKfVM05KjWUXQ/s640/009.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="406" data-original-width="640" height="406" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgqLJsiOF8XpsacxHlf-LOCMqLMDaHWFrUHMX9MjzOWqTSAC4dBhX2DEIgBXRJv2_WO_xhpVR4gvyaUG6HLwW5WP_atjb9-q-QFLhLWD2-ogX2gPoqxPahyew-kgNJtNgLKfVM05KjWUXQ/w640-h406/009.png" width="640" /></a></div>
<h3 id="インストールパラメータでkickstartファイルを指定">4. インストールパラメータでkickstartファイルを指定</h3>
<p>インストールパラメータでは、以下の通り、<code>init.ks</code>のパラメータを追記する。追記箇所を間違えないよう注意。</p>
<pre><code>linuxefi /images/pxeboot/vmlinuz inst.stage2=hd:LABEL=RHEL-8-3-0-BaseOS-x86_64 quiet inst.ks=nfs:192.168.11.13:/Public2/ks/ks_rhel8.cfg
</code></pre>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiQc6T5pSzNt9AbQ-Xti4NTHlPlEw1e_LebO55mn-xvXMoHKArrG8LAOn6eEBAnTxlvu2aRDGQVtQKhNZj41mWMcuC9VhZEkQIAGBgZxHCSP9Mn_c-H2K5pedBCsnoruZWSi8b7pnaANdc/s680/006.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="419" data-original-width="680" height="394" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiQc6T5pSzNt9AbQ-Xti4NTHlPlEw1e_LebO55mn-xvXMoHKArrG8LAOn6eEBAnTxlvu2aRDGQVtQKhNZj41mWMcuC9VhZEkQIAGBgZxHCSP9Mn_c-H2K5pedBCsnoruZWSi8b7pnaANdc/w640-h394/006.png" width="640" /></a></div>
<p>パラメータ追記後、「Ctrl + x」を押してインストールを開始する。</p>
<h3 id="自動インストール開始">5. 自動インストール開始</h3>
<p>Kickstartによる自動インストールが成功した場合は、以下画面のように「Starting automated install」といった表示がされ、自動的にインストールが進む。</p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCW8jPNs86T1kuGUIdbuKA-cnwXfF1lzXk06h-PQVfOdtU7PyTCZolVvMY4-eR7AZLpQ4_TaN1vVeWy-evwNG_cmhFuUcb_JMacAjr4o_PJ-bSmCBCELZntmIaDcTitzeKGo2XN5j12Ds/s1024/010.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="771" data-original-width="1024" height="482" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCW8jPNs86T1kuGUIdbuKA-cnwXfF1lzXk06h-PQVfOdtU7PyTCZolVvMY4-eR7AZLpQ4_TaN1vVeWy-evwNG_cmhFuUcb_JMacAjr4o_PJ-bSmCBCELZntmIaDcTitzeKGo2XN5j12Ds/w640-h482/010.png" width="640" /></a></div>
<p>なお、Kickstartファイルにて<code>lang ja_JP.UTF-8</code>を設定した場合、<strong>インストールは実行されるが、文字化けする</strong>ので注意。文字化けを回避するため、前述したKickstartファイルでは、<code>%post</code>の処理で言語設定を変更するようにしている。</p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEijNIoa9Q1TkksXVHKAJdzEal3aJOUA4ZKtt2TpBauDlajSKsx1lIeCN34tInXt-XYZLiyeqthXpbFLUalVyiwEXrhdVPbGXVyVx-B05pFqdYXewy1OCdCgxJLi3Cvf3rJ9UDs5_fC2uq8/s1026/005.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="769" data-original-width="1026" height="480" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEijNIoa9Q1TkksXVHKAJdzEal3aJOUA4ZKtt2TpBauDlajSKsx1lIeCN34tInXt-XYZLiyeqthXpbFLUalVyiwEXrhdVPbGXVyVx-B05pFqdYXewy1OCdCgxJLi3Cvf3rJ9UDs5_fC2uq8/w640-h480/005.png" width="640" /></a></div>
<p>インストール完了後、自動で再起動がされ、ログインプロンプトが表示されればインストール完了となる。</p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-dKw40gxxq8D3lLy6MjXdlsbXGR2Av4SvqSI0q82bp0wzPI6zg9kgS7YccC-Skcx79-mNNL7h5dgwwZO0l48MERhlIJCfOwtGwFyj3X5omGjdcCVg-Ix1j-CxJpP3qGjcy4iwq0HqpEU/s537/011.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="175" data-original-width="537" height="208" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-dKw40gxxq8D3lLy6MjXdlsbXGR2Av4SvqSI0q82bp0wzPI6zg9kgS7YccC-Skcx79-mNNL7h5dgwwZO0l48MERhlIJCfOwtGwFyj3X5omGjdcCVg-Ix1j-CxJpP3qGjcy4iwq0HqpEU/w640-h208/011.png" width="640" /></a></div>
<h3 id="インストール後の確認">6. インストール後の確認</h3>
<p>インストール完了後、SSHでログインし以下であることを確認した。Kickstartにより問題なく初期設定がされていることが確認できた。</p>
<ul>
<li>言語設定が<code>ja_JP.UTF-8</code>であること</li>
<li>タイムゾーンが<code>Asia/Tokyo</code>であること</li>
<li>Chronyにて指定したNTPサーバと同期していること</li>
<li><code>open-vm-tools</code>がインストールされ起動していること</li>
<li>SELinuxが無効化されていること</li>
<li>firewalldのサービスが停止していること</li>
</ul>
<pre><code># localectl
System Locale: LANG=ja_JP.UTF-8
VC Keymap: jp
X11 Layout: jp
# timedatectl
Local time: 土 2021-05-08 17:46:57 JST
Universal time: 土 2021-05-08 08:46:57 UTC
RTC time: 土 2021-05-08 08:46:57
Time zone: Asia/Tokyo (JST, +0900)
System clock synchronized: yes
NTP service: active
RTC in local TZ: no
# chronyc -n sources
210 Number of sources = 1
MS Name/IP address Stratum Poll Reach LastRx Last sample
===============================================================================
^* 192.168.33.23 2 6 377 54 +208us[ +253us] +/- 2101us
# systemctl status vmtoolsd
● vmtoolsd.service - Service for virtual machines hosted on VMware
Loaded: loaded (/usr/lib/systemd/system/vmtoolsd.service; enabled; vendor pr>
Active: active (running) since Sat 2021-05-08 16:17:38 JST; 1h 29min ago
Docs: http://github.com/vmware/open-vm-tools
Main PID: 988 (vmtoolsd)
Tasks: 3 (limit: 10900)
Memory: 6.5M
CGroup: /system.slice/vmtoolsd.service
mq988 /usr/bin/vmtoolsd
5月 08 16:17:38 localhost.localdomain systemd[1]: Started Service for virtual >
# getenforce
Disabled
# systemctl status firewalld
● firewalld.service - firewalld - dynamic firewall daemon
Loaded: loaded (/usr/lib/systemd/system/firewalld.service; disabled; vendor >
Active: inactive (dead)
Docs: man:firewalld(1)
</code></pre>
<h2 id="参考">参考</h2>
<ul>
<li><a href="https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/9/html-single/performing_an_advanced_rhel_9_installation/index#kickstart-commands-for-system-configuration_kickstart-commands-and-options-reference">付録B キックスタートのコマンドおよびオプションの参照</a></li>
</ul><h2 style="text-align: left;">更新履歴</h2><div><ul style="text-align: left;"><li>2021/5/8 新規作成</li><li>2023/12/30 RHEL 9の情報を追記</li></ul></div>
tech-mmmmhttp://www.blogger.com/profile/01739191108051432575noreply@blogger.com0tag:blogger.com,1999:blog-7885523125238064555.post-23597452754440585662023-12-23T11:00:00.002+09:002023-12-28T05:57:40.114+09:00UbuntuにZabbix Agent 2をインストールする手順<p>Zabbix Agentは過去のバージョンから利用されているZabbix Agentとは別に、新たにGo言語ベースで作り直されたZabbix Agent 2が存在する。</p>
<p>過去Windows環境にZabbix Agent 2をインストールする手順は記載した。</p>
<ul>
<li><a href="https://tech-mmmm.blogspot.com/2023/05/windowszabbix-agent-2.html">Windows用Zabbix Agent 2インストール手順</a></li>
</ul>
<p>今回は、<strong>Ubuntuに対してZabbix Agent 2をインストールする手順</strong>を記載する。</p>
<h2 id="環境">環境</h2>
<p>導入対象となるOSとZabbixのバージョンは以下の通り。</p>
<ul>
<li>OS : Ubuntu 22.04.2 LTS</li>
<li>Zabbix Agent 2 : 6.0</li>
</ul>
<p>Ubuntuは初期状態では<code>curl</code>コマンドが使えない場合があるので、その場合は以下の通りインストールをしておくこと。</p>
<pre><code>$ sudo apt install curl
</code></pre>
<h2 id="手順">手順</h2>
<h3 id="zabbix-releaseをインストール">1. <code>zabbix-release</code>をインストール</h3>
<p>以下URLから最新の<code>zabbix-release</code>のパッケージファイルのURLを確認する。</p>
<table>
<thead>
<tr>
<th>バージョン</th>
<th>URL</th>
</tr>
</thead>
<tbody>
<tr>
<td>6.0</td>
<td><a href="https://repo.zabbix.com/zabbix/6.0/ubuntu/pool/main/z/zabbix-release/">https://repo.zabbix.com/zabbix/6.0/ubuntu/pool/main/z/zabbix-release/</a></td>
</tr>
<tr>
<td>6.2</td>
<td><a href="https://repo.zabbix.com/zabbix/6.2/ubuntu/pool/main/z/zabbix-release/">https://repo.zabbix.com/zabbix/6.2/ubuntu/pool/main/z/zabbix-release/</a></td>
</tr>
<tr>
<td>6.4</td>
<td><a href="https://repo.zabbix.com/zabbix/6.4/ubuntu/pool/main/z/zabbix-release/">https://repo.zabbix.com/zabbix/6.4/ubuntu/pool/main/z/zabbix-release/</a></td>
</tr>
</tbody>
</table><p>今回の場合は、Ubuntu 22.04.2 LTSに対して、Zabbix 6.0のエージェントをインストールすることから、<code>https://repo.zabbix.com/zabbix/6.0/ubuntu/pool/main/z/zabbix-release/zabbix-release_latest%2Bubuntu22.04_all.deb</code>を<code>curl</code>を使ってダウンロードしてインストールする。</p>
<pre><code>$ curl -LO https://repo.zabbix.com/zabbix/6.0/ubuntu/pool/main/z/zabbix-release/zabbix-release_latest%2Bubuntu22.04_all.deb
$ sudo dpkg -i zabbix-release_latest%2Bubuntu22.04_all.deb
以前に未選択のパッケージ zabbix-release を選択しています。
(データベースを読み込んでいます ... 現在 204627 個のファイルとディレクトリがインストールされています。)
zabbix-release_latest%2Bubuntu22.04_all.deb を展開する準備をしています ...
zabbix-release (1:6.0-4+ubuntu22.04) を展開しています...
zabbix-release (1:6.0-4+ubuntu22.04) を設定しています ...
$ sudo apt update
</code></pre>
<h3 id="zabbix-agnet-2をインストール">2. Zabbix Agnet 2をインストール</h3>
<pre><code>$ apt search zabbix-agent
ソート中... 完了
全文検索... 完了
pcp-export-zabbix-agent/jammy 5.3.6-1build1 amd64
Module for exporting PCP metrics to Zabbix agent
zabbix-agent/jammy 1:6.0.25-1+ubuntu22.04 amd64
Zabbix network monitoring solution - agent
zabbix-agent-dbgsym/jammy 1:6.0.25-1+ubuntu22.04 amd64
debug symbols for zabbix-agent
zabbix-agent2/jammy 1:6.0.25-1+ubuntu22.04 amd64
Zabbix network monitoring solution - agent
zabbix-agent2-dbgsym/jammy 1:6.0.25-1+ubuntu22.04 amd64
debug symbols for zabbix-agent2
zabbix-agent2-plugin-mongodb/jammy 1:6.0.25-1+ubuntu22.04 amd64
Zabbix Agent2 plugin for monitoring MongoDB installations
zabbix-agent2-plugin-postgresql/jammy 1:6.0.25-2+ubuntu22.04 amd64
Zabbix Agent2 plugin for monitoring PostgreSQL installations
</code></pre>
<pre><code>$ sudo apt install zabbix-agent2
$ systemctl status zabbix-agent2
● zabbix-agent2.service - Zabbix Agent 2
Loaded: loaded (/lib/systemd/system/zabbix-agent2.service; enabled; vendor preset: enabled)
Active: active (running) since Sat 2023-12-16 20:34:53 JST; 25s ago
Main PID: 4798 (zabbix_agent2)
Tasks: 10 (limit: 4599)
Memory: 4.5M
CPU: 21ms
CGroup: /system.slice/zabbix-agent2.service
mq4798 /usr/sbin/zabbix_agent2 -c /etc/zabbix/zabbix_agent2.conf
12月 16 20:34:53 t1082ubnt systemd[1]: Started Zabbix Agent 2.
12月 16 20:34:53 t1082ubnt zabbix_agent2[4798]: Starting Zabbix Agent 2 (6.0.25)
12月 16 20:34:53 t1082ubnt zabbix_agent2[4798]: Zabbix Agent2 hostname: [Zabbix server]
12月 16 20:34:53 t1082ubnt zabbix_agent2[4798]: Press Ctrl+C to exit.
</code></pre>
<h3 id="設定ファイルを修正">3. 設定ファイルを修正</h3>
<p><code>/etc/zabbix/zabbix_agent2.conf</code>のファイルを修正し、Zabbix Serverと疎通できるようにする。最低限以下の通り設定すれば動作する。</p>
<pre><code>Server=[Zabbix ServerのIPアドレス]
ServerActive=[Zabbix ServerのIPアドレス]
Hostname=[Ubuntuのホスト名]
</code></pre>
<p>設定反映のため、Zabbix Agent 2を再起動する。</p>
<pre><code>$ sudo systemctl restart zabbix-agent2
</code></pre>
<p>以上で、Ubuntuに対してZabbix Agent 2をインストールする手順は完了となる。</p>
tech-mmmmhttp://www.blogger.com/profile/01739191108051432575noreply@blogger.com0tag:blogger.com,1999:blog-7885523125238064555.post-51916113955472539702023-12-16T11:00:00.007+09:002023-12-16T11:00:00.143+09:00Kubernetesにてノードの削除・追加を行う<p>Kubernetesでノードの調子が悪くなったりした際に、一度ノードを削除して同じ名前で再度追加をさせたい場合がある。</p>
<p>簡単にノードを削除・追加するだけであればよいが、Kubernetesの場合、少し追加で必要な作業がある。本記事では、<strong>Kubernetesにてノードの削除・追加を行うために必要な手順</strong>を記載する。</p>
<h2 id="環境">環境</h2>
<p>以下に今回構築する各種ソフトウェアのバージョンを記載する。</p>
<ul>
<li>ホストOS : AlmaLinux 8.6</li>
<li>Kubernetes : v1.28.2</li>
<li>Docker : 24.0.6</li>
<li>CRI : cri-dockerd 0.3.4</li>
<li>CNI : flannel v0.22.0</li>
</ul>
<p>今回の構成の概要図を以下に記載する。</p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiHG7Yy7sgqHe2vjVpdE56BHkgXWvz1hJRR_XKYBdTFsvUYqgSp77lR9wvUgeFNFSTeOzbELVycWVKLaCjOl4KP9jnpOHKW0lw_mBdVjv0fMQr7VujsLUL1RMJAJf3PiXW5ghGwx7f5nLOiulRC-FLXaRiSx3PZXg-hLVIayMwZBm8orSF1ijxqkjAVO7c/s3077/%E6%A7%8B%E6%88%90%E5%9B%B34.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1519" data-original-width="3077" height="316" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiHG7Yy7sgqHe2vjVpdE56BHkgXWvz1hJRR_XKYBdTFsvUYqgSp77lR9wvUgeFNFSTeOzbELVycWVKLaCjOl4KP9jnpOHKW0lw_mBdVjv0fMQr7VujsLUL1RMJAJf3PiXW5ghGwx7f5nLOiulRC-FLXaRiSx3PZXg-hLVIayMwZBm8orSF1ijxqkjAVO7c/w640-h316/%E6%A7%8B%E6%88%90%E5%9B%B34.png" width="640" /></a></div>
<p>作業前のKubernetesのノードの状態は以下の通り。3台目に存在する「t1053kube」のノードを削除したのち、追加する手順を説明する。</p>
<pre><code># kubectl get node -o=wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
t1051kube Ready control-plane 202d v1.28.2 192.168.11.51 <none> AlmaLinux 8.6 (Sky Tiger) 4.18.0-372.9.1.el8.x86_64 docker://24.0.6
t1052kube Ready control-plane 202d v1.28.2 192.168.11.52 <none> AlmaLinux 8.6 (Sky Tiger) 4.18.0-372.9.1.el8.x86_64 docker://24.0.6
t1053kube Ready control-plane 174d v1.28.2 192.168.11.53 <none> AlmaLinux 8.6 (Sky Tiger) 4.18.0-372.9.1.el8.x86_64 docker://24.0.6
</code></pre>
<h2 id="ノード削除手順">ノード削除手順</h2>
<h3 id="kubernetesクラスタからノードを削除">1. Kubernetesクラスタからノードを削除</h3>
<p>Kubernetesクラスタからノードを削除する際は、<code>kubectl delete node [ノード名]</code>で行う。処理はすぐに完了する。</p>
<pre><code># kubectl delete node t1053kube
node "t1053kube" deleted
</code></pre>
<p>3台存在したノードが2台になったことが確認できる。</p>
<pre><code># kubectl get node -o=wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
t1051kube Ready control-plane 202d v1.28.2 192.168.11.51 <none> AlmaLinux 8.6 (Sky Tiger) 4.18.0-372.9.1.el8.x86_64 docker://24.0.6
t1052kube Ready control-plane 202d v1.28.2 192.168.11.52 <none> AlmaLinux 8.6 (Sky Tiger) 4.18.0-372.9.1.el8.x86_64 docker://24.0.6
</code></pre>
<h3 id="ノードをリセット">2. ノードをリセット</h3>
<p>削除した対象のOSにログインし、<code>kubeadm reset</code>を用いて、一度ノードをリセットする。なお、複数のCRIがインストールされている環境の場合は、<code>--cri-socket</code>オプションにて使用するCRIを明記する必要がある(オプションを指定しない場合、<code>Found multiple CRI endpoints on the host.</code>というエラーが表示されコマンドが失敗する)。</p>
<pre><code># kubeadm reset --cri-socket=unix:///var/run/cri-dockerd.sock
[reset] Reading configuration from the cluster...
[reset] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -o yaml'
W1210 07:53:07.866239 247333 reset.go:120] [reset] Unable to fetch the kubeadm-config ConfigMap from cluster: failed to get node registration: failed to get node name from kubelet config: open /etc/kubernetes/kubelet.conf: no such file or directory
W1210 07:53:07.866312 247333 preflight.go:56] [reset] WARNING: Changes made to this host by 'kubeadm init' or 'kubeadm join' will be reverted.
[reset] Are you sure you want to proceed? [y/N]: y ★"y"を入力
[preflight] Running pre-flight checks
W1210 07:53:09.421805 247333 removeetcdmember.go:106] [reset] No kubeadm config, using etcd pod spec to get data directory
[reset] Deleted contents of the etcd data directory: /var/lib/etcd
[reset] Stopping the kubelet service
[reset] Unmounting mounted directories in "/var/lib/kubelet"
[reset] Deleting contents of directories: [/etc/kubernetes/manifests /var/lib/kubelet /etc/kubernetes/pki]
[reset] Deleting files: [/etc/kubernetes/admin.conf /etc/kubernetes/kubelet.conf /etc/kubernetes/bootstrap-kubelet.conf /etc/kubernetes/controller-manager.conf /etc/kubernetes/scheduler.conf]
The reset process does not clean CNI configuration. To do so, you must remove /etc/cni/net.d
The reset process does not reset or clean up iptables rules or IPVS tables.
If you wish to reset iptables, you must do so manually by using the "iptables" command.
If your cluster was setup to utilize IPVS, run ipvsadm --clear (or similar)
to reset your system's IPVS tables.
The reset process does not clean your kubeconfig files and you must remove them manually.
Please, check the contents of the $HOME/.kube/config file.
</code></pre>
<h3 id="etcdからnode情報を削除">3. etcdからNode情報を削除</h3>
<p>Kubernetesクラスタから削除しても、etcdからは情報が削除されない。そこで、直接etcdのPodにログインし削除作業を行う。etcdにログインすると、プロンプトが<code>sh-5.1#</code>に変わる。</p>
<pre><code># kubectl exec -it -n kube-system etcd-t1051kube -- sh
sh-5.1#
</code></pre>
<p>etcdの操作は<code>etcdctl</code>コマンドで実行する。オプションが多いため超絶コマンドが長いが、以下の通り<code>etcdctl member list</code>を実行すると、現在etcdに登録されている情報を確認することができる。先ほどKubernetesクラスタから削除した「t1053kube」のノードの情報が残っていることがわかる。</p>
<pre><code>sh-5.1# ETCDCTL_API=3 etcdctl --cert=/etc/kubernetes/pki/etcd/peer.crt --key=/etc/kubernetes/pki/etcd//peer.key --cacert=/etc/kubernetes/pki/etcd/ca.crt --endpoints=https://127.0.0.1:2379 member list
391db64cfd0b76da, started, t1052kube, https://192.168.11.52:2380, https://192.168.11.52:2379, false
40f1e9f856640698, started, t1051kube, https://192.168.11.51:2380, https://192.168.11.51:2379, false
a642d0757a50ab59, started, t1053kube, https://192.168.11.53:2380, https://192.168.11.53:2379, false
</code></pre>
<p>テーブル形式でもう少し見やすくする場合は、<code>etcdctl -w table member list</code>を実行する。</p>
<pre><code>sh-5.1# ETCDCTL_API=3 etcdctl --cert=/etc/kubernetes/pki/etcd/peer.crt --key=/etc/kubernetes/pki/etcd//peer.key --cacert=/etc/kubernetes/pki/etcd/ca.crt --endpoints=https://127.0.0.1:2379 -w table member list
+------------------+---------+-----------+----------------------------+----------------------------+------------+
| ID | STATUS | NAME | PEER ADDRS | CLIENT ADDRS | IS LEARNER |
+------------------+---------+-----------+----------------------------+----------------------------+------------+
| 391db64cfd0b76da | started | t1052kube | https://192.168.11.52:2380 | https://192.168.11.52:2379 | false |
| 40f1e9f856640698 | started | t1051kube | https://192.168.11.51:2380 | https://192.168.11.51:2379 | false |
| a642d0757a50ab59 | started | t1053kube | https://192.168.11.53:2380 | https://192.168.11.53:2379 | false |
+------------------+---------+-----------+----------------------------+----------------------------+------------+
</code></pre>
<p>削除対象の「t1053kube」のIDを引数として、<code>etcdctl member remove [ID]</code>を実行する。</p>
<pre><code>sh-5.1# ETCDCTL_API=3 etcdctl --cert=/etc/kubernetes/pki/etcd/peer.crt --key=/etc/kubernetes/pki/etcd//peer.key --cacert=/etc/kubernetes/pki/etcd/ca.crt --endpoints=https://127.0.0.1:2379 member remove a642d0757a50ab59
Member a642d0757a50ab59 removed from cluster 786da9e9c378caa1
</code></pre>
<p>再度登録状況を確認すると、「t1053kube」が削除されていることが確認できる。</p>
<pre><code>sh-5.1# ETCDCTL_API=3 etcdctl --cert=/etc/kubernetes/pki/etcd/peer.crt --key=/etc/kubernetes/pki/etcd//peer.key --cacert=/etc/kubernetes/pki/etcd/ca.crt --endpoints=https://127.0.0.1:2379 -w table member list
+------------------+---------+-----------+----------------------------+----------------------------+------------+
| ID | STATUS | NAME | PEER ADDRS | CLIENT ADDRS | IS LEARNER |
+------------------+---------+-----------+----------------------------+----------------------------+------------+
| 391db64cfd0b76da | started | t1052kube | https://192.168.11.52:2380 | https://192.168.11.52:2379 | false |
| 40f1e9f856640698 | started | t1051kube | https://192.168.11.51:2380 | https://192.168.11.51:2379 | false |
+------------------+---------+-----------+----------------------------+----------------------------+------------+
</code></pre>
<p>最後に<code>exit</code>でetcdから抜けておく。</p>
<pre><code>sh-5.1# exit
</code></pre>
<h2 id="ノード参加手順">ノード参加手順</h2>
<h3 id="参加するためのtoken作成">1. 参加するためのtoken作成</h3>
<p>ノード参加のためには、tokenを作成する必要がある。現在作成されているtokenは以下コマンドで確認できる。何も表示されない場合は、未登録であることを意味する。</p>
<pre><code># kubeadm token list
</code></pre>
<p>tokenを作成しつつノード追加のコマンドを表示させるため、以下コマンドを実行する。</p>
<pre><code># kubeadm token create --print-join-command
kubeadm join t1041kube.intrat.local:6443 --token hqrq5b.lmlys2u5vsqmza06 --discovery-token-ca-cert-hash sha256:cd21077ae8389da3990d28424f3e8aa1fcbf5394094bcb849803b8664d700b55
</code></pre>
<p>また、ノード追加時に必要となる証明書の更新も実施する。</p>
<pre><code># kubeadm init phase upload-certs --upload-certs
[upload-certs] Storing the certificates in Secret "kubeadm-certs" in the "kube-system" Namespace
[upload-certs] Using certificate key:
36568d37aa84232e623cd8df34c1704c2fb16e7846e7df92b55f13072ce262f0
</code></pre>
<p>再度tokenを確認すると、tokenと証明書の2行が表示されていることが確認できる。</p>
<pre><code># kubeadm token list
TOKEN TTL EXPIRES USAGES DESCRIPTION EXTRA GROUPS
hqrq5b.lmlys2u5vsqmza06 23h 2023-12-10T22:41:01Z authentication,signing <none> system:bootstrappers:kubeadm:default-node-token
x87o7b.ya73txnsszqsx8x5 1h 2023-12-10T00:58:59Z <none> Proxy for managing TTL for the kubeadm-certs secret <none>
</code></pre>
<h3 id="kubectl-joinコマンド実行">2. <code>kubectl join</code>コマンド実行</h3>
<p>token作成時に生成した<code>kubeadm join</code>コマンドを実行し、ノードを再参加させる。なお、コントロールプレーンとして追加する場合は、<code>--control-plane</code>や<code>--certificate-key</code>のオプション指定が追加で必要となる。<code>--cri-socket</code>は前述したとおり、複数のCRIがインストールされている環境の場合に必要となる。</p>
<p>今回の場合はコントロールプレーンとしてノードを参加させるため、コマンドは以下のようになった。</p>
<pre><code>kubeadm join t1041kube.intrat.local:6443 --token hqrq5b.lmlys2u5vsqmza06 \
--discovery-token-ca-cert-hash sha256:cd21077ae8389da3990d28424f3e8aa1fcbf5394094bcb849803b8664d700b55 \
--control-plane \
--certificate-key 36568d37aa84232e623cd8df34c1704c2fb16e7846e7df92b55f13072ce262f0 \
--cri-socket=unix:///var/run/cri-dockerd.sock
</code></pre>
<p>実際の実行結果は以下となる。</p>
<pre><code># kubeadm join t1041kube.intrat.local:6443 --token hqrq5b.lmlys2u5vsqmza06 \
> --discovery-token-ca-cert-hash sha256:cd21077ae8389da3990d28424f3e8aa1fcbf5394094bcb849803b8664d700b55 \
> --control-plane \
> --certificate-key 36568d37aa84232e623cd8df34c1704c2fb16e7846e7df92b55f13072ce262f0 \
> --cri-socket=unix:///var/run/cri-dockerd.sock
[preflight] Running pre-flight checks
[preflight] Reading configuration from the cluster...
[preflight] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -o yaml'
[preflight] Running pre-flight checks before initializing the new control plane instance
[preflight] Pulling images required for setting up a Kubernetes cluster
[preflight] This might take a minute or two, depending on the speed of your internet connection
[preflight] You can also perform this action in beforehand using 'kubeadm config images pull'
W1210 08:16:25.328679 250776 checks.go:835] detected that the sandbox image "registry.k8s.io/pause:3.6" of the container runtime is inconsistent with that used by kubeadm. It is recommended that using "registry.k8s.io/pause:3.9" as the CRI sandbox image.
[download-certs] Downloading the certificates in Secret "kubeadm-certs" in the "kube-system" Namespace
[download-certs] Saving the certificates to the folder: "/etc/kubernetes/pki"
[certs] Using certificateDir folder "/etc/kubernetes/pki"
[certs] Generating "etcd/server" certificate and key
[certs] etcd/server serving cert is signed for DNS names [localhost t1053kube] and IPs [192.168.11.53 127.0.0.1 ::1]
[certs] Generating "etcd/peer" certificate and key
[certs] etcd/peer serving cert is signed for DNS names [localhost t1053kube] and IPs [192.168.11.53 127.0.0.1 ::1]
[certs] Generating "apiserver-etcd-client" certificate and key
[certs] Generating "etcd/healthcheck-client" certificate and key
[certs] Generating "front-proxy-client" certificate and key
[certs] Generating "apiserver" certificate and key
[certs] apiserver serving cert is signed for DNS names [kubernetes kubernetes.default kubernetes.default.svc kubernetes.default.svc.cluster.local t1041kube.intrat.local t1053kube] and IPs [10.96.0.1 192.168.11.53]
[certs] Generating "apiserver-kubelet-client" certificate and key
[certs] Valid certificates and keys now exist in "/etc/kubernetes/pki"
[certs] Using the existing "sa" key
[kubeconfig] Generating kubeconfig files
[kubeconfig] Using kubeconfig folder "/etc/kubernetes"
[kubeconfig] Writing "admin.conf" kubeconfig file
[kubeconfig] Writing "controller-manager.conf" kubeconfig file
[kubeconfig] Writing "scheduler.conf" kubeconfig file
[control-plane] Using manifest folder "/etc/kubernetes/manifests"
[control-plane] Creating static Pod manifest for "kube-apiserver"
[control-plane] Creating static Pod manifest for "kube-controller-manager"
[control-plane] Creating static Pod manifest for "kube-scheduler"
[check-etcd] Checking that the etcd cluster is healthy
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[kubelet-start] Starting the kubelet
[kubelet-start] Waiting for the kubelet to perform the TLS Bootstrap...
[etcd] Announced new etcd member joining to the existing etcd cluster
[etcd] Creating static Pod manifest for "etcd"
[etcd] Waiting for the new etcd member to join the cluster. This can take up to 40s
The 'update-status' phase is deprecated and will be removed in a future release. Currently it performs no operation
[mark-control-plane] Marking the node t1053kube as control-plane by adding the labels: [node-role.kubernetes.io/control-plane node.kubernetes.io/exclude-from-external-load-balancers]
[mark-control-plane] Marking the node t1053kube as control-plane by adding the taints [node-role.kubernetes.io/control-plane:NoSchedule]
This node has joined the cluster and a new control plane instance was created:
* Certificate signing request was sent to apiserver and approval was received.
* The Kubelet was informed of the new secure connection details.
* Control plane label and taint were applied to the new node.
* The Kubernetes control plane instances scaled up.
* A new etcd member was added to the local/stacked etcd cluster.
To start administering your cluster from this node, you need to run the following as a regular user:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
Run 'kubectl get nodes' to see this node join the cluster.
</code></pre>
<p>最後にノードの状態を確認すると「t1053kube」が正常に登録されステータスがReadyになっていることがわかる。</p>
<pre><code># kubectl get node -o=wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
t1051kube Ready control-plane 202d v1.28.2 192.168.11.51 <none> AlmaLinux 8.6 (Sky Tiger) 4.18.0-372.9.1.el8.x86_64 docker://24.0.6
t1052kube Ready control-plane 202d v1.28.2 192.168.11.52 <none> AlmaLinux 8.6 (Sky Tiger) 4.18.0-372.9.1.el8.x86_64 docker://24.0.6
t1053kube Ready control-plane 17s v1.28.2 192.168.11.53 <none> AlmaLinux 8.6 (Sky Tiger) 4.18.0-372.9.1.el8.x86_64 docker://24.0.6
</code></pre>
<p>以上で、Kubernetesにてノードの削除・追加を行うために必要な手順は完了となる。</p>
tech-mmmmhttp://www.blogger.com/profile/01739191108051432575noreply@blogger.com0tag:blogger.com,1999:blog-7885523125238064555.post-26930283069785297472023-12-09T10:41:00.001+09:002023-12-09T10:41:00.129+09:00RHEL 9のsshdでPermitRootLoginなどを設定する方法<p>先日、RHEL 9互換OSのAlmaLinux 9を使った際に、SSHで直接rootログインを禁止しようと、<code>PermitRootLogin no</code>の設定を<code>/etc/ssh/sshd_config</code>に記載した。</p>
<p>しかし、記載したにも関わらずSSHでrootログインできてしまうという事象が発生した。調べてみると、RHEL 9からはsshdの設定方法が少し変更となったようだ。</p>
<p>本記事では、<strong>RHEL 9のsshdでPermitRootLoginなどを設定する方法</strong>を記載する。</p>
<h2 id="環境">環境</h2>
<ul>
<li>OS : Red Hat Enterprise Linux release 9.2</li>
</ul>
<h2 id="設定手順">設定手順</h2>
<p>RHEL 7や8などでは<code>/etc/ssh/sshd_config</code>にPermitRootLoginの設定を実施すれば問題なかったが、RHEL 9からは追加の設定は<code>/etc/ssh/sshd_config.d/</code>のディレクトリ内の設定ファイルに記載する方式に変わっている。</p>
<p><code>/etc/ssh/sshd_config</code>を確認すると、以下の通りディレクトリ内の設定ファイルをIncludeする設定が記載されている。</p>
<pre><code># cat /etc/ssh/sshd_config | grep -B3 'Include'
# To modify the system-wide sshd configuration, create a *.conf file under
# /etc/ssh/sshd_config.d/ which will be automatically included below
Include /etc/ssh/sshd_config.d/*.conf
</code></pre>
<p>実際に<code>/etc/ssh/sshd_config.d/</code>のディレクトリを見ると、以下の通り2つのファイルが存在した。</p>
<pre><code># ls -l /etc/ssh/sshd_config.d/
合計 8
-rw-r--r--. 1 root root 141 10月 6 20:08 01-permitrootlogin.conf
-rw-------. 1 root root 719 1月 16 2023 50-redhat.conf
</code></pre>
<p>今回はPermitRootLoginの設定なので、<code>01-permitrootlogin.conf</code>のファイルを編集する。</p>
<pre><code># cat /etc/ssh/sshd_config.d/01-permitrootlogin.conf
PermitRootLogin no # noに変更しSSHによるrootログインを拒否する
</code></pre>
<p>設定後、sshdをリロードすれば完了となる。</p>
<pre><code># systemctl reload sshd
</code></pre>
<p>以上で、RHEL 9のsshdでPermitRootLoginなどを設定する方法は完了となる。</p>
tech-mmmmhttp://www.blogger.com/profile/01739191108051432575noreply@blogger.com0tag:blogger.com,1999:blog-7885523125238064555.post-11285392236341293862023-12-02T11:00:00.005+09:002023-12-02T15:24:53.058+09:00ソースからインストールしたOpenLDAPのSSL有効化手順<p>先日、RHEL 9にOpenLDAPをソースからインストールする手順を記載した。</p>
<ul>
<li><a href="https://tech-mmmm.blogspot.com/2023/11/openldap.html">OpenLDAPをソースからインストールする</a></li>
</ul>
<p>上記手順ではLDAPのみ有効としており、通信が暗号化されていない。LDAPでは通信を暗号化する方法としてLDAPS (LDAP over SSL/TLS) があり、OpenLDAPにおいても設定を有効化することでLDAPS通信を利用できる。</p>
<p>本記事では、<strong>ソースからインストールOpenLDAPに対してSSLを有効化する手順</strong>を記載する。</p>
<h2 id="環境">環境</h2>
<p>今回は以下のOSに対してインストールを行った。OpenLDAPは本記事作成時のLTSリリースの最新版である2.5.16をダウンロードした。</p>
<ul>
<li>OS : RHEL 9</li>
<li>OpenLDAP : 2.5.16</li>
</ul>
<p>OpenLDAPのドメイン等の情報は以下とする。</p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>設定値</th>
</tr>
</thead>
<tbody>
<tr>
<td>ドメイン</td>
<td><code>dc=example,dc=com</code></td>
</tr>
<tr>
<td>RootDN</td>
<td><code>cn=Manager,dc=example,dc=com</code></td>
</tr>
<tr>
<td>OU</td>
<td><code>ou=group,dc=example,dc=com</code></td>
</tr>
<tr>
<td>グループ</td>
<td><code>cn=ldapgrp,ou=group,dc=example,dc=com</code></td>
</tr>
<tr>
<td>ユーザ1</td>
<td><code>uid=user01,ou=group,dc=example,dc=com</code></td>
</tr>
<tr>
<td>ユーザ2</td>
<td><code>uid=user01,ou=group,dc=example,dc=com</code></td>
</tr>
</tbody>
</table><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjMDWvhe8dvFcxi3pnj3wcHoOwn9ar-VH3xwICzwxqCYTH20yOI1z-4vQFVcJ5ncWEtx-ApP2-5lt_7viEX4k18m6qye9G9kJ_VSYOWjE6Yv6E18AUMOaE-59ecWjwvvqavwMh6-CSMBYdIMYpl80Se0RHuStBwPDZ_qsryAgAuc8dH1j5Brk_8L8n1its/s2048/000.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1191" data-original-width="2048" height="372" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjMDWvhe8dvFcxi3pnj3wcHoOwn9ar-VH3xwICzwxqCYTH20yOI1z-4vQFVcJ5ncWEtx-ApP2-5lt_7viEX4k18m6qye9G9kJ_VSYOWjE6Yv6E18AUMOaE-59ecWjwvvqavwMh6-CSMBYdIMYpl80Se0RHuStBwPDZ_qsryAgAuc8dH1j5Brk_8L8n1its/w640-h372/000.png" width="640" /></a></div>
<h2 id="openldapをソースからインストール">OpenLDAPをソースからインストール</h2>
<p>OpenLDAPをソースからインストールする手順は、以下記事の通り実施する。</p>
<ul>
<li>URL</li>
</ul>
<h2 id="openldap-ssl有効化手順">OpenLDAP SSL有効化手順</h2>
<h3 id="証明書作成">1. 証明書作成</h3>
<p>OpenLDAPをSSLするための公開鍵と秘密鍵を作成する。作成した鍵は<code>/etc/openldap/certs/</code>に配置するため、あらかじめ移動しておく。</p>
<pre><code># cd /etc/openldap/certs/
</code></pre>
<p>秘密鍵を作成する。</p>
<pre><code># openssl genrsa 2048 > ldaps.key
</code></pre>
<p>秘密鍵をもとにCSRを作成する。</p>
<pre><code># openssl req -new -key ldaps.key > ldaps.csr
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:JP
State or Province Name (full name) []:Tokyo
Locality Name (eg, city) [Default City]:
Organization Name (eg, company) [Default Company Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []:LDAPS
Email Address []:
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
</code></pre>
<p>公開鍵に埋め込むSAN (サブジェクト代替名) の情報をテキストファイルで作成しておく。今回はOpenLDAPのドメイン (<code>example.com</code>) とOpenLDAPサーバのIPアドレス (192.168.11.191) で設定した。</p>
<pre><code># cat << EOF > san.txt
subjectAltName = DNS:*.example.com, IP:192.168.11.191
EOF
</code></pre>
<p>最後にCSRとSANの情報を用いて公開鍵を作成する。</p>
<pre><code># openssl x509 -days 3650 -req -signkey ldaps.key -in ldaps.csr -out ldaps.crt -extfile san.txt
Certificate request self-signature ok
subject=C = JP, ST = Tokyo, L = Default City, O = Default Company Ltd, CN = LDAPS
</code></pre>
<p>最終的に以下4つのファイルが作成される。</p>
<pre><code># ls -l
合計 16
-rw-r--r--. 1 root root 1302 10月 29 08:11 ldaps.crt
-rw-r--r--. 1 root root 997 10月 29 08:10 ldaps.csr
-rw-r--r--. 1 root root 1704 10月 29 08:10 ldaps.key
-rw-r--r--. 1 root root 54 10月 29 08:07 san.txt
</code></pre>
<h3 id="ssl有効化用ldifファイルを作成">2. SSL有効化用LDIFファイルを作成</h3>
<p>OpenLDAPの設定は、LDIF (LDAP Interchange Format)と呼ばれる設定ファイルを読み込ませることで行う。</p>
<p>まずは、以下の通りLDIFファイルを作成する。</p>
<pre><code># cd ~
# cat << EOF > ssl.ldif
dn: cn=config
changetype: modify
replace: olcTLSCertificateFile
olcTLSCertificateFile: /etc/openldap/certs/ldaps.crt
-
replace: olcTLSCertificateKeyFile
olcTLSCertificateKeyFile: /etc/openldap/certs/ldaps.key
EOF
</code></pre>
<p>反映は<code>slapmodify</code>コマンドで行う。</p>
<pre><code># /usr/sbin/slapmodify -v -n 0 -F /etc/openldap/slapd.d -l ssl.ldif
modify: "cn=config" (00000001)
Closing DB...
</code></pre>
<p>なお、<code>ldapadd</code>コマンドでは<code>Insufficient access (50)</code>で失敗するため設定変更できないため注意しよう。</p>
<pre><code># ldapadd -Y EXTERNAL -H ldapi:// -f ssl.ldif
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
modifying entry "cn=config"
ldap_modify: Insufficient access (50)
</code></pre>
<h3 id="systemdの設定を修正">3. systemdの設定を修正</h3>
<p>systemdでOpenLDAPのサービス起動時のコマンドにおいて、LDAPSを受け付けするよう設定追加を行う。</p>
<pre><code># vi /etc/systemd/system/slapd.service
[Unit]
Description=OpenLDAP server
After=syslog.target network.target
[Service]
Type=forking
User=root
Group=root
PIDFile=/usr/var/run/slapd.pid
ExecStart=/usr/libexec/slapd -F /etc/openldap/slapd.d -h 'ldapi:/// ldap:/// ldaps:///' ←★「ldaps:///」を追加
ExecReload=/bin/kill -HUP $MAINPID
ExecStop=/bin/kill -TERM $MAINPID
[Install]
WantedBy=multi-user.target
</code></pre>
<p>設定を反映させる。</p>
<pre><code># systemctl daemon-reload
# systemctl restart slapd
</code></pre>
<p>反映後、LDAPSのポート番号である636が開放されていることを確認する。</p>
<pre><code># ss -nl | egrep '389|636'
tcp LISTEN 0 2048 0.0.0.0:389 0.0.0.0:*
tcp LISTEN 0 2048 0.0.0.0:636 0.0.0.0:*
tcp LISTEN 0 2048 [::]:389 [::]:*
tcp LISTEN 0 2048 [::]:636 [::]:*
</code></pre>
<h3 id="ldp.exeを使った確認">4. <code>LDP.exe</code>を使った確認</h3>
<p>実際に、外部からアクセスできることをWindows Serverの<code>LDP.exe</code>を利用して確認する。なお、<code>LDP.exe</code>は、役割管理ツールの「AD DSおよびAD LDSツール」に含まれる</p>
<p>なお、LDAPSはそのままでは<code>LDP.exe</code>にて接続することができず、<strong>OpenLDAPサーバにて作成したSSLサーバ証明書の公開鍵である<code>ldaps.crt</code>を「信頼されたルート証明機関」として登録が必要</strong>となる。</p>
<p><code>/etc/openldap/certs/ldaps.crt</code>を<code>LDP.exe</code>を実行するサーバにダウンロードし、ファイルをダブルクリックすると証明書の情報を確認することができ、「証明書のインストール」を選択することで「証明書のインポートウィザード」を開始できる。</p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjnmzob8SjOX-P-kp4cDsbAezmW_fLPff-2VZjqotDwDcj4ilFj-O8ew9GTw3EbvKg4owLWzMUhuFR0ozCDx8JyPoaLeJHIl5jR7KV6Oh95Xl4kqGAAUa9Byw_bmEaiV2ZCVXV8SheVnmNQ3PPjC9QhuGnUXzoWXIODx4BmJiEi2J_3i2G8ojAj5UHloZs/s587/033.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="587" data-original-width="470" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjnmzob8SjOX-P-kp4cDsbAezmW_fLPff-2VZjqotDwDcj4ilFj-O8ew9GTw3EbvKg4owLWzMUhuFR0ozCDx8JyPoaLeJHIl5jR7KV6Oh95Xl4kqGAAUa9Byw_bmEaiV2ZCVXV8SheVnmNQ3PPjC9QhuGnUXzoWXIODx4BmJiEi2J_3i2G8ojAj5UHloZs/w320-h400/033.png" width="320" /></a></div><p></p>
<p>インポートウィザードでは証明書ストアにて「信頼されたルート証明機関」を選択する。</p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjnADLE0ZSaOAQpEY5F-55nw_2L_O09eSluxWDOf7f6FjxSaZkWC3sSevogrrjCJYRvsJX_BDFf5cK_D6yu05WVmmyVPLCslovcKtbWgIkl2MmWDdT1fMLzSzTwhIWEeSrBp3ZkLKDMYAbLfSq0qErIbZP94tyb1Xf2O7-g9T9bqgw12y7ccR7CseRi3nE/s614/034.png" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" data-original-height="578" data-original-width="614" height="376" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjnADLE0ZSaOAQpEY5F-55nw_2L_O09eSluxWDOf7f6FjxSaZkWC3sSevogrrjCJYRvsJX_BDFf5cK_D6yu05WVmmyVPLCslovcKtbWgIkl2MmWDdT1fMLzSzTwhIWEeSrBp3ZkLKDMYAbLfSq0qErIbZP94tyb1Xf2O7-g9T9bqgw12y7ccR7CseRi3nE/w400-h376/034.png" width="400" /></a></div><p></p>
<p>セキュリティ警告が表示される場合があるが、自己署名証明書による証明書エラーとなることから、そのまま「はい」を選択する。</p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgINuQbX7SJa-HqO49n-40fe-zricfE2CRB_n-dSswZaPGUgQ2IIeYE_FIChV7rAmmdKZ4QjhZyWO_J6r-wsZREdb50zGPBgyacdbBIIf_sQ1p18rR_SIQL1Qf30IQM6Y792zr8x9MzzvGmlwjmeQHTJMl52c8MvJxqEEhzN1oaa2y5Ssj6WNb2TQ4zQiY/s413/035.png" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" data-original-height="354" data-original-width="413" height="343" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgINuQbX7SJa-HqO49n-40fe-zricfE2CRB_n-dSswZaPGUgQ2IIeYE_FIChV7rAmmdKZ4QjhZyWO_J6r-wsZREdb50zGPBgyacdbBIIf_sQ1p18rR_SIQL1Qf30IQM6Y792zr8x9MzzvGmlwjmeQHTJMl52c8MvJxqEEhzN1oaa2y5Ssj6WNb2TQ4zQiY/w400-h343/035.png" width="400" /></a></div><p></p>
<p>証明書をインポートしたのち、再度<code>LDP.exe</code>にて接続すると、以下の通りSSLによる接続に成功する。</p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEisMnRg8gbTwaPerX8QD_jJCV6EPZppnnAVQFjjfUQcLrsRUoRS-y6cw1463PluRRDyXs_ldIlGVZ2ywG_-lOfpUAQFjQxPxA3lfS4RugpoEcuAD3DjMKG0gvWOKIIROFxm_4QFM0xdUTLKA619xcWOfJ2hiKXiy70PtL-JQBkDOCWGRKe9MXsEKBXVXOI/s830/037.png" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" data-original-height="572" data-original-width="830" height="442" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEisMnRg8gbTwaPerX8QD_jJCV6EPZppnnAVQFjjfUQcLrsRUoRS-y6cw1463PluRRDyXs_ldIlGVZ2ywG_-lOfpUAQFjQxPxA3lfS4RugpoEcuAD3DjMKG0gvWOKIIROFxm_4QFM0xdUTLKA619xcWOfJ2hiKXiy70PtL-JQBkDOCWGRKe9MXsEKBXVXOI/w640-h442/037.png" width="640" /></a></div><p></p>
<p>以上で、ソースからインストールOpenLDAPに対してSSLを有効化する手順は完了となる。</p>
tech-mmmmhttp://www.blogger.com/profile/01739191108051432575noreply@blogger.com0tag:blogger.com,1999:blog-7885523125238064555.post-13045789733961732802023-11-25T11:30:00.002+09:002023-11-25T11:30:00.135+09:00OpenLDAPをソースからインストールする<p>OpenLDAPはRHEL 7までは、リポジトリから<code>yum</code>コマンドを使ってインストールすることができたが、RHEL 8になってからOpenLDAPは含まれないようになってしまい、RHELのサポート範囲外のソフトウェアとなってしまった。</p>
<p>RHEL 8以降は、OpenLDAPからRed Hat Directory Server (RHDS) を利用することができる。しかし、RHDSは389 Directory Serverがベースとなっており、OpenLDAPや構築方法や運用方法が異なってしまう。</p>
<p>以上より、RHEL 8以降においてもOpenLDAPが利用するため、本記事では、<strong>RHEL 9にOpenLDAPをソースからインストールする手順</strong>を記載する。</p>
<h2 id="環境">環境</h2>
<p>今回は以下のOSに対してインストールを行った。OpenLDAPは本記事作成時のLTSリリースの最新版である2.5.16をダウンロードした。</p>
<ul>
<li>OS : RHEL 9</li>
<li>OpenLDAP : 2.5.16</li>
</ul>
<p>OpenLDAPのドメイン等の情報は以下とする。</p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>設定値</th>
</tr>
</thead>
<tbody>
<tr>
<td>ドメイン</td>
<td><code>dc=example,dc=com</code></td>
</tr>
<tr>
<td>RootDN</td>
<td><code>cn=Manager,dc=example,dc=com</code></td>
</tr>
<tr>
<td>OU</td>
<td><code>ou=group,dc=example,dc=com</code></td>
</tr>
<tr>
<td>グループ</td>
<td><code>cn=ldapgrp,ou=group,dc=example,dc=com</code></td>
</tr>
<tr>
<td>ユーザ1</td>
<td><code>uid=user01,ou=group,dc=example,dc=com</code></td>
</tr>
<tr>
<td>ユーザ2</td>
<td><code>uid=user01,ou=group,dc=example,dc=com</code></td>
</tr>
</tbody>
</table><div class="separator" style="clear: both; text-align: center;"><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjEwKFEXnzFRK7nt4g2mf8Zz3lEqu7IMSD8J9alSJ0pyc1IiRa88qwI5iNpUpg1ZerrQOn7OLK2UiBT-n6SyVZBCFEmSGAA7IEFDamYPHpFAIDidwXPOCTCl8OyMn2UWmMiUh7cd-hQWU_okryL5L8FqFI0kczxnwHeHEOcTRbuI-wWqneu-9aWVFX6UKk/s2048/000.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1191" data-original-width="2048" height="372" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjEwKFEXnzFRK7nt4g2mf8Zz3lEqu7IMSD8J9alSJ0pyc1IiRa88qwI5iNpUpg1ZerrQOn7OLK2UiBT-n6SyVZBCFEmSGAA7IEFDamYPHpFAIDidwXPOCTCl8OyMn2UWmMiUh7cd-hQWU_okryL5L8FqFI0kczxnwHeHEOcTRbuI-wWqneu-9aWVFX6UKk/w640-h372/000.png" width="640" /></a></div>
<h2 id="openldapインストール">OpenLDAPインストール</h2>
<h3 id="openldapのソースを入手">1. OpenLDAPのソースを入手</h3>
<p>OpenLDAPのソースは以下からダウンロードできる。今回はLTSリリースである2.5.16をダウンロードした。</p>
<ul>
<li><a href="https://www.openldap.org/software/download/">https://www.openldap.org/software/download/</a></li>
</ul>
<p>ファイル名は<code>openldap-2.5.16.tgz</code>となる。以下の通り解凍して、解凍後のディレクトリ内に移動しておく。</p>
<pre><code># tar zxf openldap-2.5.16.tgz
# cd openldap-2.5.16
</code></pre>
<h3 id="前提パッケージインストール">2. 前提パッケージインストール</h3>
<p>ビルド時にエラーや警告が表示されないように、以下前提パッケージのインストールを行う。</p>
<pre><code># dnf install gcc make cyrus-sasl-devel openssl-devel systemd-devel -y
</code></pre>
<h3 id="makefile作成">3. <code>Makefile</code>作成</h3>
<p><code>./configure</code>を実行してMakefileを作成する。オプションは以下の通り設定する。なお、設定可能なオプションは他にも多数あり、<code>./configure --help</code>にて確認することができる。</p>
<table>
<thead>
<tr>
<th>オプション</th>
<th>説明</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>--with-tls</code></td>
<td>SSL/TLSを有効化。</td>
</tr>
<tr>
<td><code>--with-cyrus-sasl</code></td>
<td>SASLによる認証を有効化。</td>
</tr>
<tr>
<td><code>--enable-crypt</code></td>
<td>パスワードの暗号化を有効化。</td>
</tr>
<tr>
<td><code>--prefix=/usr</code></td>
<td>インストールディレクトリを変更。デフォルトは<code>/usr/local/</code>となる。</td>
</tr>
<tr>
<td><code>--sysconfdir=/etc</code></td>
<td>設定ファイル配置ディレクトリを変更。デフォルトは<code>/usr/local/etc</code>となる。</td>
</tr>
</tbody>
</table><p><code>./configure</code>の実行結果を以下に記載する。</p>
<pre><code># ./configure --with-tls --with-cyrus-sasl --enable-crypt --with-systemd --prefix=/usr --sysconfdir=/etc
Configuring OpenLDAP 2.5.16-Release ...
checking build system type... x86_64-pc-linux-gnu
checking host system type... x86_64-pc-linux-gnu
checking target system type... x86_64-pc-linux-gnu
checking configure arguments... done
checking for cc... cc
checking for ar... ar
checking for strip... strip
checking whether make sets $(MAKE)... yes
~(中略)~
config.status: executing libtool commands
config.status: executing default commands
Making servers/slapd/backends.c
Add config ...
Add ldif ...
Add monitor ...
Add mdb ...
Add relay ...
Making servers/slapd/overlays/statover.c
Add syncprov ...
Please run "make depend" to build dependencies
</code></pre>
<p><code>Makefile</code>が作成されていることを確認しておく。</p>
<pre><code># ls -l Makefile
-rw-r--r--. 1 root root 9256 10月 14 07:16 Makefile
</code></pre>
<h3 id="依存関係チェック">4. 依存関係チェック</h3>
<p>作成したMakfefileで依存関係をチェックする。特にエラーがなければ問題ない。</p>
<pre><code># make depend
Making depend in /root/openldap-2.5.16
Entering subdirectory include
make[1]: ディレクトリ '/root/openldap-2.5.16/include' に入ります
Making ldap_config.h
make[1]: ディレクトリ '/root/openldap-2.5.16/include' から出ます
~(中略)~
Entering subdirectory man8
make[3]: ディレクトリ '/root/openldap-2.5.16/doc/man/man8' に入ります
make[3]: 'depend' に対して行うべき事はありません.
make[3]: ディレクトリ '/root/openldap-2.5.16/doc/man/man8' から出ます
make[2]: ディレクトリ '/root/openldap-2.5.16/doc/man' から出ます
make[1]: ディレクトリ '/root/openldap-2.5.16/doc' から出ます
</code></pre>
<h3 id="ビルド実行">5. ビルド実行</h3>
<p>ビルド実行する。1~2分程度で完了する。</p>
<pre><code>#make
Making all in /root/openldap-2.5.16
Entering subdirectory include
make[1]: ディレクトリ '/root/openldap-2.5.16/include' に入ります
make[1]: 'all' に対して行うべき事はありません.
make[1]: ディレクトリ '/root/openldap-2.5.16/include' から出ます
~(中略)~
make[3]: ディレクトリ '/root/openldap-2.5.16/doc/man/man8' から出ます
make[2]: ディレクトリ '/root/openldap-2.5.16/doc/man' から出ます
make[1]: ディレクトリ '/root/openldap-2.5.16/doc' から出ます
</code></pre>
<h3 id="インストール">6. インストール</h3>
<p>ビルド後、インストールを実行する。なお、インストール前に<code>make test</code>コマンドでインストール前のテストを行うことができるので、安全にインストールを進めたい場合は実行すること。<code>make test</code>は数分~数十分時間を要する。</p>
<pre><code># make install
Making all in /root/openldap-2.5.16
Entering subdirectory include
make[1]: ディレクトリ '/root/openldap-2.5.16/include' に入ります
make[1]: 'all' に対して行うべき事はありません.
make[1]: ディレクトリ '/root/openldap-2.5.16/include' から出ます
~(中略)~
installing slappasswd.8 in /usr/share/man/man8
installing slapschema.8 in /usr/share/man/man8
installing slaptest.8 in /usr/share/man/man8
make[3]: ディレクトリ '/root/openldap-2.5.16/doc/man/man8' から出ます
make[2]: ディレクトリ '/root/openldap-2.5.16/doc/man' から出ます
make[1]: ディレクトリ '/root/openldap-2.5.16/doc' から出ます
</code></pre>
<p>以上で、OpenLDAPのソースからのインストールは完了となる。続けて初期設定を行う。</p>
<h2 id="openldap初期設定">OpenLDAP初期設定</h2>
<h3 id="初期設定">1. 初期設定</h3>
<p>設定ファイルをバックアップしておく。</p>
<pre><code># cd ~
# cp -R /etc/openldap ~/openldap.org
# ls -ld ~/openldap.org
drwxr-xr-x. 4 root root 163 10月 14 07:37 /root/openldap.org
</code></pre>
<p>OpenLDAPの管理用ユーザーのパスワードを<code>slappasswd</code>を使って生成する。</p>
<pre><code># slappasswd
New password:
Re-enter new password:
{SSHA}7B1EpVxClcKpBwnlqG73YtB7IrUXhTLM
</code></pre>
<p>設定ファイルを以下の通り追記・変更を行う。<code>include</code>ではOpenLDAPで必要となるスキーマを追加している。<code>olcSuffix</code>や<code>olcRootDN</code>はOpenLDAPのドメインに変更を行う。<code>olcRootPW</code>は先ほど生成したパスワードを指定する。</p>
<pre><code># vi /etc/openldap/slapd.ldif
~(中略)~
include: file:///etc/openldap/schema/core.ldif
include: file:///etc/openldap/schema/cosine.ldif #<-★追記
include: file:///etc/openldap/schema/inetorgperson.ldif #<-★追記
include: file:///etc/openldap/schema/nis.ldif #<-★追記
~(中略)~
dn: olcDatabase=mdb,cn=config
objectClass: olcDatabaseConfig
objectClass: olcMdbConfig
olcDatabase: mdb
olcDbMaxSize: 1073741824
olcSuffix: dc=example,dc=com #<-★変更
olcRootDN: cn=Manager,dc=example,dc=com #<-★変更
# Cleartext passwords, especially for the rootdn, should
# be avoided. See slappasswd(8) and slapd-config(5) for details.
# Use of strong authentication encouraged.
olcRootPW: {SSHA}7B1EpVxClcKpBwnlqG73YtB7IrUXhTLM #<-★変更
~(以下略)~
</code></pre>
<p>設定ファイルの前後で<code>diff</code>した結果は以下の通り。</p>
<pre><code># diff /etc/openldap/slapd.ldif{,.default}
44,46d43
< include: file:///etc/openldap/schema/cosine.ldif
< include: file:///etc/openldap/schema/inetorgperson.ldif
< include: file:///etc/openldap/schema/nis.ldif
87,88c84,85
< olcSuffix: dc=example,dc=com
< olcRootDN: cn=Manager,dc=example,dc=com
---
> olcSuffix: dc=my-domain,dc=com
> olcRootDN: cn=Manager,dc=my-domain,dc=com
92c89
< olcRootPW: {SSHA}7B1EpVxClcKpBwnlqG73YtB7IrUXhTLM
---
> olcRootPW: secret
</code></pre>
<p>OpenLDAPのデータ格納に必要となるディレクトリを作成する。</p>
<pre><code># mkdir /usr/var/openldap-data
# mkdir /etc/openldap/slapd.d
</code></pre>
<p><code>slapadd</code>コマンドで設定反映を行う。</p>
<pre><code># /usr/sbin/slapadd -v -n 0 -F /etc/openldap/slapd.d -l /etc/openldap/slapd.ldif
added: "cn=config" (00000001)
added: "cn=schema,cn=config" (00000001)
added: "cn={0}core,cn=schema,cn=config" (00000001)
added: "cn={1}cosine,cn=schema,cn=config" (00000001)
added: "cn={2}inetorgperson,cn=schema,cn=config" (00000001)
added: "cn={3}nis,cn=schema,cn=config" (00000001)
added: "olcDatabase={-1}frontend,cn=config" (00000001)
added: "olcDatabase={1}mdb,cn=config" (00000001)
added: "olcDatabase={2}monitor,cn=config" (00000001)
Closing DB...
</code></pre>
<h3 id="openldap起動確認">2. OpenLDAP起動確認</h3>
<p>まずは手動でOpenLDAPを起動し、正常に起動することを確認する。</p>
<pre><code># /usr/libexec/slapd -F /etc/openldap/slapd.d -h 'ldapi:/// ldap:/// ldaps:///'
</code></pre>
<p>起動後に、<code>ldapsearch</code>で問題なく情報の参照ができるか確認する。</p>
<pre><code># ldapsearch -x -b '' -s base '(objectclass=*)' namingContexts
# extended LDIF
#
# LDAPv3
# base <> with scope baseObject
# filter: (objectclass=*)
# requesting: namingContexts
#
#
dn:
namingContexts: dc=example,dc=com ←★設定したドメインが表示されることを確認
# search result
search: 2
result: 0 Success
# numResponses: 2
# numEntries: 1
</code></pre>
<p>確認後、一度OpenLDAPを停止しておく。</p>
<pre><code># ps -ef | grep slapd | grep -v grep
root 69944 1 0 08:29 ? 00:00:00 /usr/libexec/slapd -F /etc/openldap/slapd.d -h ldapi:/// ldap:/// ldaps:///
# pkill slapd
# ps -ef | grep slapd | grep -v grep
#
</code></pre>
<h3 id="systemdへ登録">3. systemdへ登録</h3>
<p>RHELの場合、systemdでサービスの起動・停止を制御できた方が便利となる。以下の通り、systemdにOpenLDAPのサービスを登録するための設定ファイルを作成する。</p>
<pre><code># cat << 'EOF' > /etc/systemd/system/slapd.service
[Unit]
Description=OpenLDAP server
After=syslog.target network.target
[Service]
Type=forking
User=root
Group=root
PIDFile=/usr/var/run/slapd.pid
ExecStart=/usr/libexec/slapd -F /etc/openldap/slapd.d -h 'ldapi:/// ldap:/// ldaps:///'
ExecReload=/bin/kill -HUP $MAINPID
ExecStop=/bin/kill -TERM $MAINPID
[Install]
WantedBy=multi-user.target
EOF
</code></pre>
<p>上記ファイルを作成後、<code>systemctl</code>コマンドで起動停止が問題なくできることを確認しておく。</p>
<pre><code># systemctl daemon-reload
# systemctl start slapd
# systemctl enable slapd
# systemctl status slapd
● slapd.service - OpenLDAP server
Loaded: loaded (/etc/systemd/system/slapd.service; enabled; preset: disabled)
Active: active (running) since Sat 2023-10-14 08:43:52 JST; 8s ago
Main PID: 70011 (slapd)
Tasks: 2 (limit: 23166)
Memory: 5.0M
CPU: 8ms
CGroup: /system.slice/slapd.service
mq70011 /usr/libexec/slapd -F /etc/openldap/slapd.d -h "ldapi:/// ldap:/// ldaps:///"
10月 14 08:43:52 t1191rhel systemd[1]: Starting OpenLDAP server...
10月 14 08:43:52 t1191rhel slapd[70010]: @(#) $OpenLDAP: slapd 2.5.16 (Oct 14 2023 07:29:29) $
root@t1191rhel:/root/openldap-2.5.16/servers/slapd
10月 14 08:43:52 t1191rhel slapd[70011]: slapd starting
10月 14 08:43:52 t1191rhel systemd[1]: Started OpenLDAP server.
# systemctl stop slapd
# systemctl status slapd
○ slapd.service - OpenLDAP server
Loaded: loaded (/etc/systemd/system/slapd.service; enabled; preset: disabled)
Active: inactive (dead) since Sat 2023-10-14 18:28:23 JST; 1s ago
Duration: 9h 44min 31.510s
Process: 70408 ExecStop=/bin/kill -TERM $MAINPID (code=exited, status=0/SUCCESS)
Main PID: 70011 (code=exited, status=0/SUCCESS)
CPU: 14ms
10月 14 08:44:24 t1191rhel slapd[70011]: conn=1001 op=3 ADD dn="cn=ldapgrp,ou=group,dc=example,dc=com"
10月 14 08:44:24 t1191rhel slapd[70011]: conn=1001 op=3 RESULT tag=105 err=0 qtime=0.000010 etime=0.000472 text=
10月 14 08:44:24 t1191rhel slapd[70011]: conn=1001 op=4 UNBIND
10月 14 08:44:24 t1191rhel slapd[70011]: conn=1001 fd=13 closed
10月 14 18:28:23 t1191rhel systemd[1]: Stopping OpenLDAP server...
10月 14 18:28:23 t1191rhel slapd[70011]: daemon: shutdown requested and initiated.
10月 14 18:28:23 t1191rhel slapd[70011]: slapd shutdown: waiting for 0 operations/tasks to finish
10月 14 18:28:23 t1191rhel slapd[70011]: slapd stopped.
10月 14 18:28:23 t1191rhel systemd[1]: slapd.service: Deactivated successfully.
10月 14 18:28:23 t1191rhel systemd[1]: Stopped OpenLDAP server.
</code></pre>
<p>起動・停止が問題なくできることが確認できたら、OpenLDAPは起動させておこう。</p>
<pre><code># systemctl start slapd
</code></pre>
<h3 id="ユーザー登録確認">4. ユーザー登録確認</h3>
<p>ここからは実際にOpenLDAPにグループやユーザーの登録を行ってみよう。</p>
<p>まずは、ドメイン、OU、グループの登録を行うためのLDIFファイルを作成する。</p>
<pre><code># cat << EOF > base.ldif
dn: dc=example,dc=com
objectClass: top
objectClass: dcObject
objectClass: organization
dc: example
o: Example Inc.
dn: ou=group,dc=example,dc=com
objectClass: organizationalUnit
ou: Group
dn: cn=ldapgrp,ou=group,dc=example,dc=com
objectClass: posixGroup
gidNumber: 10000
cn: ldapgrp
EOF
</code></pre>
<p><code>ldapadd</code>コマンドで登録を行う。パスワードは初期設定時に生成したパスワードとなる。</p>
<pre><code># ldapadd -x -D "cn=Manager,dc=example,dc=com" -W -f base.ldif
Enter LDAP Password:
adding new entry "dc=example,dc=com"
adding new entry "ou=group,dc=example,dc=com"
adding new entry "cn=ldapgrp,ou=group,dc=example,dc=com"
</code></pre>
<p>次にユーザー登録を行う。以下の通りLDIFファイルを作成する。</p>
<pre><code># cat << EOF > user.ldif
dn: uid=user01,ou=group,dc=example,dc=com
uid: user01
cn: Hoge Hoge
sn: user01
objectClass: posixAccount
objectClass: inetOrgPerson
userPassword: {SSHA}7B1EpVxClcKpBwnlqG73YtB7IrUXhTLM
loginShell: /bin/bash
uidNumber: 10001
gidNumber: 10000
homeDirectory: /home/user01
dn: uid=user02,ou=group,dc=example,dc=com
uid: user02
cn: Hoge Hoge
sn: user02
objectClass: posixAccount
objectClass: inetOrgPerson
userPassword: {SSHA}7B1EpVxClcKpBwnlqG73YtB7IrUXhTLM
loginShell: /bin/bash
uidNumber: 10002
gidNumber: 10000
homeDirectory: /home/user02
EOF
</code></pre>
<p><code>ldapadd</code>コマンドで登録を行う。</p>
<pre><code># ldapadd -x -D "cn=Manager,dc=example,dc=com" -W -f user.ldif
Enter LDAP Password:
adding new entry "uid=user01,ou=group,dc=example,dc=com"
adding new entry "uid=user02,ou=group,dc=example,dc=com"
</code></pre>
<p>最後に、<code>ldapsearch</code>コマンドで登録状況を確認して完了となる。</p>
<pre><code># ldapsearch -LLL -Y EXTERNAL -H ldapi:/// -b 'dc=example,dc=com'
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
dn: dc=example,dc=com
objectClass: top
objectClass: dcObject
objectClass: organization
dc: example
o: Example Inc.
dn: ou=group,dc=example,dc=com
objectClass: organizationalUnit
ou: Group
dn: cn=ldapgrp,ou=group,dc=example,dc=com
objectClass: posixGroup
gidNumber: 10000
cn: ldapgrp
dn: uid=user01,ou=group,dc=example,dc=com
uid: user01
cn: Hoge Hoge
sn: user01
objectClass: posixAccount
objectClass: inetOrgPerson
userPassword:: e1NTSEF9WFhY772eKOecgeeVpSnvvZ5YWFg=
loginShell: /bin/bash
uidNumber: 10001
gidNumber: 10000
homeDirectory: /home/user01
dn: uid=user02,ou=group,dc=example,dc=com
uid: user02
cn: Hoge Hoge
sn: user02
objectClass: posixAccount
objectClass: inetOrgPerson
userPassword:: e1NTSEF9WFhY772eKOecgeeVpSnvvZ5YWFg=
loginShell: /bin/bash
uidNumber: 10002
gidNumber: 10000
homeDirectory: /home/user02
</code></pre>
<p>以上で、RHEL 9にOpenLDAPをソースからインストールする手順は完了となる。</p>
tech-mmmmhttp://www.blogger.com/profile/01739191108051432575noreply@blogger.com0tag:blogger.com,1999:blog-7885523125238064555.post-16184473433801073802023-11-18T11:30:00.000+09:002023-11-18T11:30:00.133+09:00Grafanaインストール&Zabbixの監視データを可視化する手順<p>Grafanaは、ログやデータなどをグラフなどに可視化する、<strong>データ可視化OSS</strong>となる。Grafanaが可視化するデータを「データソース」と呼ぶ。データソースは、各種クラウド上に保存されている情報やDBなどに対応しており、それ以外にもプラグインを追加することでデータソースを追加することが可能となる。</p>
<p>本記事ではGrafanaの入門編として、<strong>GrafanaをインストールしてZabbixプラグインを追加し、Zabbixの監視データを可視化する手順</strong>を記載する。</p>
<h2 id="環境">環境</h2>
<p>Grafanaをインストールした環境は以下の通り。</p>
<ul>
<li>OS : AlmaLinux 9.2</li>
<li>Grafana : v10.0.3</li>
<li>Zabbix : 6.0.17</li>
</ul>
<h2 id="grafanaインストール手順">Grafanaインストール手順</h2>
<h3 id="grafanaのパッケージのリポジトリ設定">1, Grafanaのパッケージのリポジトリ設定</h3>
<p>Grafanaは<code>dnf</code>を使ってインストールすることができる。</p>
<p>まずは、GrafanaのリポジトリのGPGキーをダウンロードしインポートする。<code>wget</code>は環境によってはインストールされていないことから、<code>curl</code>でダウンロードした。</p>
<pre><code># curl -LO https://rpm.grafana.com/gpg.key
# rpm --import gpg.key
</code></pre>
<p>以下の通りリポジトリの設定ファイルを作成する。</p>
<pre><code># cat << EOF > /etc/yum.repos.d/grafana.repo
[grafana]
name=grafana
baseurl=https://rpm.grafana.com
repo_gpgcheck=1
enabled=1
exclude=*beta*
gpgcheck=1
gpgkey=https://rpm.grafana.com/gpg.key
sslverify=1
sslcacert=/etc/pki/tls/certs/ca-bundle.crt
EOF
</code></pre>
<h3 id="grafanaインストール">2. Grafanaインストール</h3>
<p><code>dnf</code>を使ってGrafanaをインストールする。</p>
<pre><code># dnf install grafana
AlmaLinux 9 - AppStream 1.4 MB/s | 8.8 MB 00:06
AlmaLinux 9 - BaseOS 2.4 MB/s | 2.9 MB 00:01
AlmaLinux 9 - Extras 19 kB/s | 17 kB 00:00
grafana 60 kB/s | 2.4 kB 00:00
GPG 鍵 0x2CF3C0C6 をインポート中:
Userid : "Grafana Labs <engineering@grafana.com>"
Fingerprint: 0E22 EB88 E39E 1227 7A77 60AE 9E43 9B10 2CF3 C0C6
From : https://rpm.grafana.com/gpg.key
これでよろしいですか? [y/N]: y ★yを入力してエンター
grafana 10 MB/s | 37 MB 00:03
依存関係が解決しました。
====================================================================================================================================================
パッケージ アーキテクチャー バージョン リポジトリー サイズ
====================================================================================================================================================
インストール:
grafana x86_64 10.0.3-1 grafana 79 M
依存関係のインストール:
dejavu-sans-fonts noarch 2.37-18.el9 baseos 1.3 M
fontconfig x86_64 2.14.0-2.el9_1 appstream 274 k
fonts-filesystem noarch 1:2.0.5-7.el9.1 baseos 9.0 k
freetype x86_64 2.10.4-9.el9 baseos 387 k
graphite2 x86_64 1.3.14-9.el9 baseos 94 k
harfbuzz x86_64 2.7.4-8.el9 baseos 624 k
langpacks-core-font-en noarch 3.0-16.el9 appstream 9.4 k
libpng x86_64 2:1.6.37-12.el9 baseos 116 k
urw-base35-bookman-fonts noarch 20200910-6.el9 appstream 846 k
urw-base35-c059-fonts noarch 20200910-6.el9 appstream 873 k
urw-base35-d050000l-fonts noarch 20200910-6.el9 appstream 76 k
urw-base35-fonts noarch 20200910-6.el9 appstream 9.8 k
urw-base35-fonts-common noarch 20200910-6.el9 appstream 21 k
urw-base35-gothic-fonts noarch 20200910-6.el9 appstream 642 k
urw-base35-nimbus-mono-ps-fonts noarch 20200910-6.el9 appstream 795 k
urw-base35-nimbus-roman-fonts noarch 20200910-6.el9 appstream 855 k
urw-base35-nimbus-sans-fonts noarch 20200910-6.el9 appstream 1.3 M
urw-base35-p052-fonts noarch 20200910-6.el9 appstream 973 k
urw-base35-standard-symbols-ps-fonts noarch 20200910-6.el9 appstream 41 k
urw-base35-z003-fonts noarch 20200910-6.el9 appstream 275 k
xml-common noarch 0.6.3-58.el9 appstream 31 k
トランザクションの概要
====================================================================================================================================================
インストール 22 パッケージ
ダウンロードサイズの合計: 89 M
インストール後のサイズ: 312 M
これでよろしいですか? [y/N]: y ★yを入力してエンター
~(中略)~
インストール済み:
dejavu-sans-fonts-2.37-18.el9.noarch fontconfig-2.14.0-2.el9_1.x86_64
fonts-filesystem-1:2.0.5-7.el9.1.noarch freetype-2.10.4-9.el9.x86_64
grafana-10.0.3-1.x86_64 graphite2-1.3.14-9.el9.x86_64
harfbuzz-2.7.4-8.el9.x86_64 langpacks-core-font-en-3.0-16.el9.noarch
libpng-2:1.6.37-12.el9.x86_64 urw-base35-bookman-fonts-20200910-6.el9.noarch
urw-base35-c059-fonts-20200910-6.el9.noarch urw-base35-d050000l-fonts-20200910-6.el9.noarch
urw-base35-fonts-20200910-6.el9.noarch urw-base35-fonts-common-20200910-6.el9.noarch
urw-base35-gothic-fonts-20200910-6.el9.noarch urw-base35-nimbus-mono-ps-fonts-20200910-6.el9.noarch
urw-base35-nimbus-roman-fonts-20200910-6.el9.noarch urw-base35-nimbus-sans-fonts-20200910-6.el9.noarch
urw-base35-p052-fonts-20200910-6.el9.noarch urw-base35-standard-symbols-ps-fonts-20200910-6.el9.noarch
urw-base35-z003-fonts-20200910-6.el9.noarch xml-common-0.6.3-58.el9.noarch
完了しました!
</code></pre>
<h3 id="grafana起動">3. Grafana起動</h3>
<p>インポートしそのままGrafanaは起動することができるが、もしプロキシを経由してインターネット接続を行う環境の場合は、以下の通り<code>/etc/sysconfig/grafana-server</code>にプロキシ関連の環境変数を記載しておく。</p>
<pre><code># vi /etc/sysconfig/grafana-server
# ↓最下行に以下を追加(記載例)
HTTP_PROXY=http://192.168.33.23:8080
HTTPS_PROXY=http://192.168.33.23:8080
NO_PROXY=localhost,127.0.0.1,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16
</code></pre>
<p>Grafanaを起動する。</p>
<pre><code># systemctl start grafana-server
# systemctl enable grafana-server
</code></pre>
<h3 id="grafanaにログイン">4. Grafanaにログイン</h3>
<p>Grafanaは、デフォルトではHTTPの3000番ポートで待ち受ける。以下のURLをブラウザに入力するとログイン画面が表示されるはずだ。</p>
<pre><code>http://[IPアドレス]:3000
</code></pre>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEihoAE_7DZgucTLyzQ9I0Pm_r88XZ8ReXWwCbCYEZ9cQiSdRoGX9WZuAUTywfCzfpE1DEfCsqh3zZnansC4-S7lLHuoqAbZUcueOiWNpcR-FZfx5_RBWjELL5b8AV4BeJsH1U-e9UC3GUCBXDBbbzbcvn8kqf8WvQVguYTjg2K3AEQ4EB_Utas8rIjsLqc/s918/001-2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="608" data-original-width="918" height="424" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEihoAE_7DZgucTLyzQ9I0Pm_r88XZ8ReXWwCbCYEZ9cQiSdRoGX9WZuAUTywfCzfpE1DEfCsqh3zZnansC4-S7lLHuoqAbZUcueOiWNpcR-FZfx5_RBWjELL5b8AV4BeJsH1U-e9UC3GUCBXDBbbzbcvn8kqf8WvQVguYTjg2K3AEQ4EB_Utas8rIjsLqc/w640-h424/001-2.jpg" width="640" /></a></div>
<p>ログインユーザー名、パスワードは以下を入力する。初回ログイン時はパスワード変更を求められるので、任意のパスワードに変更する。</p>
<ul>
<li>ユーザー名 : admin</li>
<li>パスワード : admin</li>
</ul>
<h2 id="zabbixのデータを可視化する">Zabbixのデータを可視化する</h2>
<h3 id="zabbixプラグインをインストール">1. Zabbixプラグインをインストール</h3>
<p>Zabbixの情報を可視化する場合、GrafanaにZabbixのプラグインをインストールする必要がある。プラグインのインストールは<code>grafana-cli</code>コマンドで行う。</p>
<pre><code># grafana-cli plugins install alexanderzobnin-zabbix-app
? Downloaded and extracted alexanderzobnin-zabbix-app v4.3.1 zip successfully to /var/lib/grafana/plugins/alexanderzobnin-zabbix-app
Please restart Grafana after installing or removing plugins. Refer to Grafana documentation for instructions if necessary.
</code></pre>
<p>プラグインインストール後、Grafanaを一度再起動しておく。</p>
<pre><code># systemctl restart grafana-server
</code></pre>
<h3 id="zabbixプラグインを有効化">2. Zabbixプラグインを有効化</h3>
<p>GrafanaのGUIにて[Administration]>[Plugins]に遷移し、[zabbix]で検索するとプラグインが表示されるので、表示されたZabbixのプラグインを選択する。</p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi6YE6n2sqhxbIgy3y6xX63Zlh7pL_ksSC4WNAzfj8Rf6HHWoAJMXBIPmSSP8AmjLgW68VMYuqTDEcpeTxgKglrnl7D4hZ9RJAdoly1gShEh6NuXL1vpt0DY93CC5_hrymu3xdlEt7co6zScL6XrbQ3bXij3spYKyzzqhLkMg2bemxQSSTvVyWMj0b4gls/s1428/004.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="679" data-original-width="1428" height="304" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi6YE6n2sqhxbIgy3y6xX63Zlh7pL_ksSC4WNAzfj8Rf6HHWoAJMXBIPmSSP8AmjLgW68VMYuqTDEcpeTxgKglrnl7D4hZ9RJAdoly1gShEh6NuXL1vpt0DY93CC5_hrymu3xdlEt7co6zScL6XrbQ3bXij3spYKyzzqhLkMg2bemxQSSTvVyWMj0b4gls/w640-h304/004.png" width="640" /></a></div>
<p>右上の[Enable]ボタンを選択する。</p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEheQkDG9WXo7Bnu7Q3NeLb2IG490lisCEid7D5AtmSRhr-4JEYJpWD16hfRVtDDRikHEVrut_BIVikCRU2BvHlYbyJJjN1IdTo8Mcw8xXcHjdQeECicu78XM081EM5FhkjyOKwHTEYXX3TxZRpQl_FyYoe3C_Y8x0L5hWcKXFHvj7JQWD57i33In9TcHEc/s1429/005.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="759" data-original-width="1429" height="340" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEheQkDG9WXo7Bnu7Q3NeLb2IG490lisCEid7D5AtmSRhr-4JEYJpWD16hfRVtDDRikHEVrut_BIVikCRU2BvHlYbyJJjN1IdTo8Mcw8xXcHjdQeECicu78XM081EM5FhkjyOKwHTEYXX3TxZRpQl_FyYoe3C_Y8x0L5hWcKXFHvj7JQWD57i33In9TcHEc/w640-h340/005.png" width="640" /></a></div>
<h3 id="データソースの設定">4. データソースの設定</h3>
<p>GrafanaのGUIにて[Administration]>[Data sources]に遷移し、[Add data source]ボタンを選択する。</p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgN9bjDLH4XdOr26c439dUMF06L4Eoa7m-uFUKBC6lq2LZzI5aOIfFkODZkGC7MMDXD1h3acSZX8k-3IWFPUWSi4Xb_NJJVabY9ewzNjtdMZQuDXdNiG8K32ghE3B-23BhYdVbZbfL1yUj07S8s-7gtTupYOZEZq7zjn_VroYvYbmnoBmV-NWIR4kZobzI/s1434/007.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="536" data-original-width="1434" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgN9bjDLH4XdOr26c439dUMF06L4Eoa7m-uFUKBC6lq2LZzI5aOIfFkODZkGC7MMDXD1h3acSZX8k-3IWFPUWSi4Xb_NJJVabY9ewzNjtdMZQuDXdNiG8K32ghE3B-23BhYdVbZbfL1yUj07S8s-7gtTupYOZEZq7zjn_VroYvYbmnoBmV-NWIR4kZobzI/w640-h240/007.png" width="640" /></a></div>
<p>データソース選択画面で[zabbix]で検索すると、1件表示されるはずなので、それを選択する。</p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZhP15rm5q6kfz4v93u4UUDasUhkYmxLF6KjXeXrvyIPpUm4VOcqam_kwJqqtXNi-Kac4CwYEKQsuDRL_HaV0GXPa4bVjKH1x79CmbrdXQqPVjxr9PrwUHYpBrlAEBeUE1jqbguV3qbTqP4pk3ZhckbhYYmK_2WlSyqdByJUNBhqvFuxwaAzpspGCyGDo/s1429/008.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="398" data-original-width="1429" height="178" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZhP15rm5q6kfz4v93u4UUDasUhkYmxLF6KjXeXrvyIPpUm4VOcqam_kwJqqtXNi-Kac4CwYEKQsuDRL_HaV0GXPa4bVjKH1x79CmbrdXQqPVjxr9PrwUHYpBrlAEBeUE1jqbguV3qbTqP4pk3ZhckbhYYmK_2WlSyqdByJUNBhqvFuxwaAzpspGCyGDo/w640-h178/008.png" width="640" /></a></div>
<p>データソース設定画面では、最低限以下を設定する。</p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>設定値</th>
</tr>
</thead>
<tbody>
<tr>
<td>Name</td>
<td>Zabbix</td>
</tr>
<tr>
<td>URL</td>
<td><code>http://[ZabbixサーバのIPアドレス]/zabbix/api_jsonrpc.php</code></td>
</tr>
<tr>
<td>Username</td>
<td>Zabbixサーバのアクセス権限があるユーザー名</td>
</tr>
<tr>
<td>Password</td>
<td>上記ユーザー名のパスワード</td>
</tr>
</tbody>
</table><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi9WTMOV3OkuOPHKyG3mAkQY7hu_Ygu2Mbaem4QmImhsN9oG_CcSb_3xx1HkLNGoO9Xs2FJVlvODOW-C5V6d91KZN4Y4RoKFyIC1Obc5XenvDdvPA2E-FdPTl94zlm04FKAcrkAo6uABTs38RlvRBzM4C-nU4Nq1vlX_WbeL1mj47ogTL-n9EHUL6GBz9I/s854/015.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="854" data-original-width="761" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi9WTMOV3OkuOPHKyG3mAkQY7hu_Ygu2Mbaem4QmImhsN9oG_CcSb_3xx1HkLNGoO9Xs2FJVlvODOW-C5V6d91KZN4Y4RoKFyIC1Obc5XenvDdvPA2E-FdPTl94zlm04FKAcrkAo6uABTs38RlvRBzM4C-nU4Nq1vlX_WbeL1mj47ogTL-n9EHUL6GBz9I/w570-h640/015.png" width="570" /></a></div>
<p>ページ下部にある[Save & test]ボタンを選択し、エラー表示されずに接続先のZabbixのバージョンが表示されれば成功となる。</p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi3ecy5VPq-l2mqv9QOpXUpoJvUEHF5rjvrPekEStmfGXYHWa8oJU-P4Q95AkqVAeFDcLX7cOaak5MV6Po278uvadBS8sfNektIaEfOqfaYim6h4Q1AMoigylIeFNJQgrtxdp33k5JGVJBgwQhs_od2dv34AChgevorJECWsT2Qek99Oa30pHauOBLsIAE/s1428/010.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="811" data-original-width="1428" height="364" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi3ecy5VPq-l2mqv9QOpXUpoJvUEHF5rjvrPekEStmfGXYHWa8oJU-P4Q95AkqVAeFDcLX7cOaak5MV6Po278uvadBS8sfNektIaEfOqfaYim6h4Q1AMoigylIeFNJQgrtxdp33k5JGVJBgwQhs_od2dv34AChgevorJECWsT2Qek99Oa30pHauOBLsIAE/w640-h364/010.png" width="640" /></a></div>
<h3 id="ダッシュボードを追加">5. ダッシュボードを追加</h3>
<p>[Dashboards]画面にてダッシュボードを作成する。</p>
<p>例えば以下はZabbixサーバの<code>/</code>領域の使用量をグラフに表示する設定となる。</p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>設定値</th>
</tr>
</thead>
<tbody>
<tr>
<td>Data source</td>
<td>Zabbix</td>
</tr>
<tr>
<td>Query type</td>
<td>Metrics</td>
</tr>
<tr>
<td>Group</td>
<td>Zabbix servers</td>
</tr>
<tr>
<td>Host</td>
<td>Zabbix server</td>
</tr>
<tr>
<td>Item tag</td>
<td>filesystem: /</td>
</tr>
<tr>
<td>Item</td>
<td>/: Used space</td>
</tr>
</tbody>
</table><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgFEymQLAIxAYzVngQ4DwVvX_02wNNvo5hXG5I986ufG0ezbrQV_xslzujOOjDxOBaR4neWI0_tqMCWDW9rq3m9n9n9oJUs1U8cElau7LBJOefVCeIh1HbdUyaGq2RcbA-_wqrkghiJgBBB4jS8x2UOU-Xfh0ZFrZ7B8qRKqUHEvvDhComNUS7pbISzryM/s1424/016.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="779" data-original-width="1424" height="350" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgFEymQLAIxAYzVngQ4DwVvX_02wNNvo5hXG5I986ufG0ezbrQV_xslzujOOjDxOBaR4neWI0_tqMCWDW9rq3m9n9n9oJUs1U8cElau7LBJOefVCeIh1HbdUyaGq2RcbA-_wqrkghiJgBBB4jS8x2UOU-Xfh0ZFrZ7B8qRKqUHEvvDhComNUS7pbISzryM/w640-h350/016.png" width="640" /></a></div>
<p>以上で、GrafanaをインストールしてZabbixの監視データを可視化する手順は完了となる。</p>
tech-mmmmhttp://www.blogger.com/profile/01739191108051432575noreply@blogger.com0tag:blogger.com,1999:blog-7885523125238064555.post-33844298530398171512023-11-11T11:00:00.027+09:002023-11-11T18:16:49.638+09:00Roundcubeを使ってWebメール環境を構築する<p>先日、Postfix+DovecotでバーチャルドメインのIMAPメールサーバーを構築する手順を記事にした。</p>
<ul>
<li><a href="https://tech-mmmm.blogspot.com/2023/11/postfixdovecotimap.html">Postfix+DovecotでバーチャルドメインのIMAPメールサーバーを構築する手順</a></li>
</ul>
<p>通常メールを確認する際は、Thunderbirdなどのメールクライアントの導入が必要となるが、メールクライアントをダウンロードしてPCにインストールしアカウントの設定を行うといった作業は、何度も実施すると結構な負荷となる。</p>
<p>そこで今回は、<strong>Webサーバ上で動作するメールクライアント「Roundcube」を使って、Webメール環境を構築</strong>してみることにした。</p>
<h2 id="環境">環境</h2>
<p>Roundcubeの必要とするDBやPHPのシステム要件は、以下を参照すること。</p>
<ul>
<li><a href="https://roundcube.net/about/">About Roundcube Webmail</a></li>
</ul>
<p>上記を踏まえ、今回Roundcubeをインストールした環境は以下の通りとした。</p>
<ul>
<li>OS : AlmaLinux 8.8</li>
<li>DB : MariaDB 10.3.35</li>
<li>Roundcube : 1.6.2</li>
<li>PHP : 7.4</li>
<li>Apache HTTP Server : 2.4.37</li>
<li>Postfix : 3.5.8</li>
<li>Dovecot : 2.3.16</li>
</ul>
<p>以下記事の手順にて、Postfix+DovecotによるSMTP/IMAPサーバが構築済みであることが前提となる。</p>
<ul>
<li><a href="https://tech-mmmm.blogspot.com/2023/11/postfixdovecotimap.html">Postfix+DovecotでバーチャルドメインのIMAPメールサーバーを構築する手順</a></li>
</ul>
<h2 id="roundcubeインストール手順">Roundcubeインストール手順</h2>
<h3 id="必要パッケージのインストール">1. 必要パッケージのインストール</h3>
<p>Roundcubeは必要となるパッケージが多岐にわたる。順にインストールしていこう。</p>
<p>まずはDBとしてMariaDBをインストールする。</p>
<pre><code>dnf install httpd mariadb-server -y
</code></pre>
<p>次にPHPをインストールする。PHPのバージョンは7.3以上であることがシステム要件となることから、今回はPHP 7.4を選定した。また、Roundcubeは公式サイトのファイルではなく、Remiリポジトリに存在するRPMパッケージにてインストールを行う。</p>
<pre><code>dnf module enable php:7.4 -y
dnf install http://rpms.remirepo.net/enterprise/remi-release-8.rpm -y
dnf --enablerepo=remi install roundcubemail -y
</code></pre>
<p>PHPにてMariaDBを利用するためのライブラリである<code>php-mysqlnd</code> (MySQL Native Driver) をインストールする。</p>
<pre><code>dnf install php-mysqlnd -y
</code></pre>
<p>ImageMagicをインストールするために必要なパッケージがインストールする。<code>gcc</code>や<code>make</code>はこの後実行する<code>pecl</code>コマンドで必要となる。</p>
<pre><code>dnf install php-devel php-pear gcc make ImageMagick ImageMagick-devel -y
</code></pre>
<p>単純にRPMパッケージをインストールするだけではRoundcubeからImageMagicを認識しないため、さらに<code>pecl</code>コマンドを実行し、ImageMagicのインストールを行う。</p>
<pre><code># pecl install imagick
WARNING: channel "pecl.php.net" has updated its protocols, use "pecl channel-update pecl.php.net" to update
downloading imagick-3.7.0.tgz ...
Starting to download imagick-3.7.0.tgz (360,138 bytes)
.........................................................................done: 360,138 bytes
33 source files, building
running: phpize
Configuring for:
PHP Api Version: 20190902
Zend Module Api No: 20190902
Zend Extension Api No: 320190902
Please provide the prefix of ImageMagick installation [autodetect] :
↑★そのままエンター
~(中略)~
Build process completed successfully
Installing '/usr/lib64/php/modules/imagick.so'
Installing '/usr/include/php/ext/imagick/php_imagick_shared.h'
install ok: channel://pecl.php.net/imagick-3.7.0
configuration option "php_ini" is not set to php.ini location
You should add "extension=imagick.so" to php.ini
</code></pre>
<p>ImageMagicのライブラリのパスを記載したPHPの設定ファイルを作成する。</p>
<pre><code># cat << EOF > /etc/php.d/20-imagick.ini
extension=/usr/lib64/php/modules/imagick.so
EOF
</code></pre>
<h3 id="mariadb設定">2. MariaDB設定</h3>
<p>ここで一度MariaDBを起動する。</p>
<pre><code>systemctl start mariadb
systemctl enable mariadb
</code></pre>
<p>MariaDBを起動したのちに、Roundcubeで用いるDB、ユーザ、パスワードを設定する。今回は以下の通り設定した。</p>
<ul>
<li>DB : roundcubemail</li>
<li>ユーザ : roundcube</li>
<li>パスワード : password</li>
</ul>
<pre><code># mysql -uroot
MariaDB [(none)]> CREATE DATABASE roundcubemail CHARACTER SET utf8 COLLATE utf8_general_ci;
MariaDB [(none)]> GRANT ALL PRIVILEGES ON roundcubemail.* TO roundcube@localhost IDENTIFIED BY 'password';
MariaDB [(none)]> FLUSH PRIVILEGES;
MariaDB [(none)]> quit
</code></pre>
<p>DBとDBユーザ作成後、初期設定用のSQLを流し込む。</p>
<pre><code># mysql -u roundcube roundcubemail -p < /usr/share/roundcubemail/SQL/mysql.initial.sql
Enter password: ←★先ほど作成したroundcubeユーザのパスワードを入力
# ←★エラーなくプロンプトが表示されればOK
</code></pre>
<h3 id="apachephp設定">3. Apache/PHP設定</h3>
<p>PHPの設定ファイルである<code>php.ini</code>は最低限タイムゾーンの設定を変更しておく。</p>
<pre><code>sed -i "s#;date.timezone =#date.timezone = 'Asia/Tokyo'#g" /etc/php.ini
</code></pre>
<p>Apacheの設定ファイルとして<code>/etc/httpd/conf.d/roundcubemail.conf</code>がインストール時に作成されるが、そのままではローカルからのアクセスのみ許可されていることから、外部からのアクセスができるよう以下コマンドを行い設定を置換する。</p>
<pre><code>sed -i 's/Require local/Require all granted/g' /etc/httpd/conf.d/roundcubemail.conf
</code></pre>
<p>最後にApacheを起動する。</p>
<pre><code>systemctl start httpd
systemctl enable httpdd
</code></pre>
<h3 id="インストールウィザードにアクセス">4. インストールウィザードにアクセス</h3>
<p>問題なくApacheが起動すれば、Roundcubeのインストールウィザード画面にアクセスできるはずだ。ブラウザから以下URLにアクセスしてみよう。</p>
<ul>
<li>http://[Roundcubeのホスト名/IPアドレス]/roundcubemail/installer/</li>
</ul>
<p>インストールウィザードでは、各種PHPのライブラリのインストール状況やDBの状況が表示される。ここでは原則<strong>すべての項目が「OK」になっていること</strong>を確認しよう(DBのみMySQLが「OK」となっていれば問題ない)。</p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhEh24gIUxxIh18XzWCqebW3zZU2F8UkOo8BB7LjSauDyA0zX0wnz48hAp9DGhTeS3i4P_OXPam3tY-Dr9OyAQ8eoOtKWubv7BPvXJ7vfeGJfh3gWXo09EKVo3xcmw-HkKakP35Ynr_rTp7ULVkv6i52ZSE1YX3HA_W3_18jXbf9u300_N-X8Mw_23fY0Y/s704/020.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="704" data-original-width="672" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhEh24gIUxxIh18XzWCqebW3zZU2F8UkOo8BB7LjSauDyA0zX0wnz48hAp9DGhTeS3i4P_OXPam3tY-Dr9OyAQ8eoOtKWubv7BPvXJ7vfeGJfh3gWXo09EKVo3xcmw-HkKakP35Ynr_rTp7ULVkv6i52ZSE1YX3HA_W3_18jXbf9u300_N-X8Mw_23fY0Y/w610-h640/020.png" width="610" /></a></div><p><br /></p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgibpV1Rpbf3y6_4WRErwfsEmALm9jPC2v6pxjrdGPYMDJbp8q6bVwkZqm2VFcDiqmqmAkjbRCD70Wd-5eyuvyLc5SaS1IN8yrWalt4L51ABsryI6R1Ah9pie7e0LCK3E4aXtmRCIL5ZPLVh1H9Att0X0LuUB_a4uMaGGk9dDxcImefZLfGVbiEJrJBrfs/s714/021.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="615" data-original-width="714" height="552" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgibpV1Rpbf3y6_4WRErwfsEmALm9jPC2v6pxjrdGPYMDJbp8q6bVwkZqm2VFcDiqmqmAkjbRCD70Wd-5eyuvyLc5SaS1IN8yrWalt4L51ABsryI6R1Ah9pie7e0LCK3E4aXtmRCIL5ZPLVh1H9Att0X0LuUB_a4uMaGGk9dDxcImefZLfGVbiEJrJBrfs/w640-h552/021.png" width="640" /></a></div>
<h3 id="config作成">5. config作成</h3>
<p>インストールウィザードではRoundcubeの各種設定を行うことができる。多数の設定項目が存在するが、最低限以下表の通り設定を行えば問題ない。</p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>説明</th>
</tr>
</thead>
<tbody>
<tr>
<td>Database setup > Database password (omit for sqlite)</td>
<td>DBのroundcubeユーザのパスワードを入力する。</td>
</tr>
<tr>
<td>IMAP Settings > username_domain</td>
<td>ここにドメインを記載すると、ログイン時にドメインを省略できる。</td>
</tr>
<tr>
<td>SMTP Settings > smtp_host</td>
<td>今回は同じサーバでSMTPサーバが動作していることから、<code>localhost:25</code>を指定する。</td>
</tr>
<tr>
<td>Display settings & user prefs > language</td>
<td>日本語環境にするため、<code>ja_JP</code>を指定する。</td>
</tr>
</tbody>
</table><p>設定後、画面下部の「CREATE CONFIG」ボタンを選択する。</p>
<h3 id="configをアップロード">6. configをアップロード</h3>
<p>設定した内容で<code>config.inc.php</code>の設定ファイルが作成され表示される。</p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-AC61OvIwUA4047F8rXIdW8K3FE4dymlxLEl6dpkNDKuJcLuItwPAxatJ31vBh0Gx02hv6OLXOnaC9dPrjUInbLBEgkdYb4TbxhPdK9dvNJXs-jW_YZJUFjQI_mn2lCi9U50w8pEMY-I31nSYuypdJIAiFpC-9pacQ4iFUCCEAaI_lzMcaml_C5MSwyM/s1080/023.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="734" data-original-width="1080" height="434" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-AC61OvIwUA4047F8rXIdW8K3FE4dymlxLEl6dpkNDKuJcLuItwPAxatJ31vBh0Gx02hv6OLXOnaC9dPrjUInbLBEgkdYb4TbxhPdK9dvNJXs-jW_YZJUFjQI_mn2lCi9U50w8pEMY-I31nSYuypdJIAiFpC-9pacQ4iFUCCEAaI_lzMcaml_C5MSwyM/w640-h434/023.png" width="640" /></a></div>
<p>表示されたconfigの内容をブラウザ上でコピーし、<code>/etc/roundcubemail/config.inc.php</code>のファイルを作成して貼り付ける。</p>
<pre><code># vi /etc/roundcubemail/config.inc.php
<?php
/* Local configuration for Roundcube Webmail */
~(中略)~
// You can connect to any other googie-compliant service by setting 'spellcheck_uri' accordingly.
$config['spellcheck_engine'] = 'enchant';
</code></pre>
<p>Roundcubeの設定反映のためApacheを再起動する。</p>
<pre><code>systemctl restart httpd
</code></pre>
<h3 id="ログイン確認">7. ログイン確認</h3>
<p>これでRoundcubeにログインできるはずだ。以下URLにアクセスしログイン画面が表示されることを確認しよう。</p>
<ul>
<li><a href="http://192.168.11.27/roundcubemail/">http://192.168.11.27/roundcubemail/</a></li>
</ul>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjnbKdiTi8fzG4AgXjqW3-ksZLmVqDlLTZOVx1euML8Yysr9ZuA19NDG1o3cIx3HryXnfFPo8RMD_Q7D65NjK6GVRMpAkGZ42_IJZtaDTDHmxDQdah4JDsrK1_4LITziwVemFYxCWhlpOIT3ydetL3vsgiXNV77e-8Te-if5xXw6HhNcBu9xfhgllQRc_w/s602/024.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="474" data-original-width="602" height="315" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjnbKdiTi8fzG4AgXjqW3-ksZLmVqDlLTZOVx1euML8Yysr9ZuA19NDG1o3cIx3HryXnfFPo8RMD_Q7D65NjK6GVRMpAkGZ42_IJZtaDTDHmxDQdah4JDsrK1_4LITziwVemFYxCWhlpOIT3ydetL3vsgiXNV77e-8Te-if5xXw6HhNcBu9xfhgllQRc_w/w400-h315/024.png" width="400" /></a></div>
<p>DovecotのIMAP認証に用いるものと同じユーザ (ローカルパートのみでOK) とパスワードを用いてログインできれば成功となる。</p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjIJzwjJGF8i7UA2rnh9dq6qtrFMffsVwpxw9AeeQQc_3exyFAIVNBN2Hrj1mKGnfgVoj4-WJf7fKnhgJJOVIpFEpJXxUTGe0TjFuzmLpuKJu-CwfPsaBufxqQG3zapJNODo1lfbA_0yLqrFoVZFXO3fvG6jy_kjZgP7pQBfpnwnrioh333uDi72wqwQDw/s1250/025.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="434" data-original-width="1250" height="222" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjIJzwjJGF8i7UA2rnh9dq6qtrFMffsVwpxw9AeeQQc_3exyFAIVNBN2Hrj1mKGnfgVoj4-WJf7fKnhgJJOVIpFEpJXxUTGe0TjFuzmLpuKJu-CwfPsaBufxqQG3zapJNODo1lfbA_0yLqrFoVZFXO3fvG6jy_kjZgP7pQBfpnwnrioh333uDi72wqwQDw/w640-h222/025.png" width="640" /></a></div>
<p>以上で、Roundcubeを使ってWebメール環境を構築する手順は完了となる。</p>
tech-mmmmhttp://www.blogger.com/profile/01739191108051432575noreply@blogger.com0tag:blogger.com,1999:blog-7885523125238064555.post-31164810779317481142023-11-04T11:00:00.001+09:002023-11-04T11:00:00.129+09:00Postfix+DovecotでバーチャルドメインのIMAPメールサーバーを構築する手順<p>先日、メールサーバー構築をする際の定番であるPostfixとDovecotを使ってIMAPのメールサーバーを構築した。</p>
<p>本記事ではその際に得られたノウハウをもとに、<strong>Postfix+DovecotでバーチャルドメインのIMAPメールサーバーを構築する手順</strong>を記載する。</p>
<h2 id="環境">環境</h2>
<p>今回Postfix及びDovecotをインストールした環境は以下の通り。</p>
<ul>
<li>OS : AlmaLinux 8.8</li>
<li>Postfix : 3.5.8</li>
<li>Dovecot : 2.3.16</li>
</ul>
<h2 id="共通">共通</h2>
<h3 id="postfix及びdovecotをインストール">1. Postfix及びDovecotをインストール</h3>
<p>Postfix及びDovecotのパッケージがインストールされていない場合は、<code>dnf</code>でインストールする。</p>
<pre><code>dnf install postfix dovecot -y
</code></pre>
<h3 id="バーチャルドメイン用のosユーザ・グループの作成">2. バーチャルドメイン用のOSユーザ・グループの作成</h3>
<p>バーチャルドメインの場合は、OSユーザではなくDovecot独自のユーザにてメールボックスのユーザが管理される。ただし、メールボックスへのメール配送等はOSユーザを用いる必要があることから、<code>vmail</code>という名前のユーザ・グループを作成する。</p>
<pre><code>groupadd -g 10000 vmail
useradd -u 10000 -g vmail vmail
</code></pre>
<h3 id="メールボックス作成">3. メールボックス作成</h3>
<p>メールボックスを<code>/var/spool/virtual</code>というディレクトリで作成する。</p>
<pre><code>mkdir /var/spool/virtual
chown -R vmail:vmail /var/spool/virtual/
</code></pre>
<p>上記ディレクトリの配下に、各ユーザのメールボックスが以下のディレクトリ構成で作成される。</p>
<pre><code>/var/spool/virtual/[ドメイン名]/[ユーザ名]/Maildir
</code></pre>
<h2 id="postfix構築手順">Postfix構築手順</h2>
<h3 id="設定ファイルバックアップ">1. 設定ファイルバックアップ</h3>
<p>設定変更の前に設定ファイルをディレクトリ丸ごとバックアップする。</p>
<pre><code>cp -rp /etc/postfix /root/postfix.org
</code></pre>
<h3 id="main.cf設定">2. <code>main.cf</code>設定</h3>
<p>Postfixの主要な設定は<code>/etc/postfix/main.cf</code>に記載する。以下に主要な設定内容を記載する。</p>
<table>
<thead>
<tr>
<th style="width: 20%;">設定項目</th>
<th style="width: 80%;">説明</th>
</tr>
</thead>
<tbody>
<tr>
<td>myhostname</td>
<td>メールサーバのホスト名をFQDNで記載する。</td>
</tr>
<tr>
<td>mydomain</td>
<td>メールサーバのドメインを記載する。今回はバーチャルドメイン環境であるため、管理対象のメールアドレスのドメインと一致しなくても問題ない。</td>
</tr>
<tr>
<td>inet_interfaces</td>
<td>外部からSMTPでアクセスできるようにallを指定する。</td>
</tr>
<tr>
<td>inet_protocols</td>
<td>今回はIPv4を指定するが、IPv4にだけでなくIPv6も使用する場合はallを指定する。</td>
</tr>
<tr>
<td>mynetworks</td>
<td>外部から接続可能なIPアドレスやネットワークを指定する。ここで設定したネットワークは後述するSASL認証も不要でメール送信が可能となるため、必必要以上に設定しないよう注意する。</td>
</tr>
<tr>
<td>relayhost</td>
<td>自ドメイン以外のメールをリレーするサーバを指定する。</td>
</tr>
<tr>
<td>home_mailbox</td>
<td>メールボックス形式をMailbox形式(ユーザ単位で1ファイルでメールを管理)またはMaildir形式(1メールに対して1ファイルで管理)で指定する。通常はMaildir形式を指定すれば問題ない。なお、Maildir形式に場合は最後に<code>/</code>を付け、<code>Maildir/</code>で指定すること。</td>
</tr>
<tr>
<td>smtpd_banner</td>
<td>メールヘッダー等に表示するメールサーバ情報を指定する。セキュリティの観点から、使用しているバージョン等は記載しない方針とし、<code>ESMTP</code>のみ設定する。</td>
</tr>
<tr>
<td>virtual_mailbox_domains</td>
<td>バーチャルドメインで管理するドメインを記載したファイルのパスを指定する。今回は、<code>/etc/postfix/vdomains</code>というファイルで管理する。</td>
</tr>
<tr>
<td>virtual_mailbox_base</td>
<td>バーチャルドメインで管理するメールボックスのディレクトリを指定する。今回は<code>/var/spool/virtual</code>を指定する。</td>
</tr>
<tr>
<td>virtual_mailbox_maps</td>
<td>バーチャルドメインで管理するユーザと、ユーザのメールボックスを紐づけするファイルのパスを指定する。今回は、<code>/etc/postfix/vmailbox</code>というファイルで管理する。なお、大規模環境においてはユーザを大量に管理する必要があることから、処理速度を考慮しハッシュ化したものを指定する(ハッシュ化は<code>postmap</code>コマンドで行う)。</td>
</tr>
<tr>
<td>virtual_uid_maps</td>
<td>バーチャルドメインでメール配送等の処理に使用するOSユーザを指定する。前述した<code>vmail</code>ユーザのUIDを指定する。</td>
</tr>
<tr>
<td>virtual_gid_maps</td>
<td>バーチャルドメインでメール配送等の処理に使用するOSグループを指定する。前述した<code>vmail</code>グループのGIDを指定する。</td>
</tr>
<tr>
<td>smtpd_sasl_auth_enable</td>
<td>SASL認証を有効にする。</td>
</tr>
<tr>
<td>smtpd_sasl_type</td>
<td>SASL認証で使用する認証先を設定する。今回はDovecotで設定するユーザ・パスワードを用いることから<code>Dovecot</code>を指定する。なお、SASLの認証設定は、後程Dovecot側でも実施する。</td>
</tr>
<tr>
<td>smtpd_sasl_path</td>
<td>PostfixとDovecotが同一環境で動作する環境であれば、<code>private/auth</code>を指定すれば問題ない。これが、通信に使用するUNIXソケットファイルのパスになる。</td>
</tr>
<tr>
<td>smtpd_sasl_security_options</td>
<td>SASL認証時のオプションを指定する。<code>noanonymous</code>にて匿名での認証を拒否し、<code>noplaintext</code>にて平文での認証を拒否する。</td>
</tr>
<tr>
<td>smtpd_recipient_restrictions</td>
<td>メールを配送する際の制限を行う。<code>permit_sasl_authenticated</code>にてSASL認証済みであれば許可し、<code>permit_mynetworks</code>にて<code>mynetworks</code>で設定したネットワークからの接続であれば許可する。最後に記載されている<code>reject</code>にて、それ以外のメール配送を拒否する。</td>
</tr>
<tr>
<td>disable_vrfy_command</td>
<td>セキュリティの観点からVRFYコマンドを禁止するため、<code>yes</code>で設定する。</td>
</tr>
<tr>
<td>smtpd_helo_required</td>
<td>セキュリティの観点からSMTPコマンド接続時のHELOコマンドを必須にするため、<code>yes</code>で設定する。</td>
</tr>
</tbody>
</table><p>実際の<code>main.cf</code>の記載例を以下に記載する。</p>
<h4 id="etcpostfixmain.cf変更箇所抜粋"><code>/etc/postfix/main.cf</code>変更箇所抜粋</h4>
<pre><code>myhostname = mx01.example.com
mydomain = example.com
inet_interfaces = all
inet_protocols = ipv4
mynetworks = 10.0.0.1
relayhost = [10.0.0.1]:25
home_mailbox = Maildir/
smtpd_banner = ESMTP
virtual_mailbox_domains = /etc/postfix/vdomains
virtual_mailbox_base = /var/spool/virtual
virtual_mailbox_maps = hash:/etc/postfix/vmailbox
virtual_uid_maps = static:10000
virtual_gid_maps = static:10000
smtpd_sasl_auth_enable = yes
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
smtpd_sasl_security_options = noanonymous, noplaintext
smtpd_recipient_restrictions = permit_sasl_authenticated, permit_mynetworks, reject
disable_vrfy_command = yes
smtpd_helo_required = yes
</code></pre>
<h3 id="バーチャルドメインの設定ファイルの作成">3. バーチャルドメインの設定ファイルの作成</h3>
<p>バーチャルドメインの設定として、以下2つのファイルを作成する。</p>
<table>
<thead>
<tr>
<th style="width: 40%;">ファイル</th>
<th style="width: 60%;">内容</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>/etc/postfix/vdomains</code></td>
<td>バーチャルドメインで管理するドメインを記載したファイル。メールサーバーで管理するドメインを一覧として記載する。</td>
</tr>
<tr>
<td><code>/etc/postfix/vmailbox</code></td>
<td>バーチャルドメインで管理するユーザと、ユーザのメールボックスを紐づけするファイル。メールアドレスとメール保存先のディレクトリを一覧として記載する。ディレクトリは、<code>[ドメイン名]/[メールアドレスのローカルパート]/Maildir/</code>の形式で記載する。</td>
</tr>
</tbody>
</table><p>それぞれのファイルの記載例を以下に記載する。</p>
<h4 id="etcpostfixvdomains"><code>/etc/postfix/vdomains</code></h4>
<pre><code>example.com
example1.com
</code></pre>
<h4 id="etcpostfixvmailbox"><code>/etc/postfix/vmailbox</code></h4>
<pre><code>ex01@example.com example.com/ex01/Maildir/
ex02@example.com example.com/ex02/Maildir/
ex11@example1.com example1.com/ex11/Maildir/
</code></pre>
<p><code>/etc/postfix/vmailbox</code>は<code>postmap</code>コマンドを用いてハッシュ化しておく。</p>
<pre><code>postmap /etc/postfix/vmailbox
</code></pre>
<h3 id="postfix設定反映">4. Postfix設定反映</h3>
<p>設定反映前に設定ファイルのチェックを行う。</p>
<pre><code># postfix check
# ←★エラーがなければ何も表示しない
</code></pre>
<p>問題がなければ、Postfixに設定を反映するため再起動する。</p>
<pre><code>systemctl restart postfix
systemctl enable postfix
</code></pre>
<h2 id="dovecot構築手順">Dovecot構築手順</h2>
<h3 id="設定ファイルバックアップ-1">1. 設定ファイルバックアップ</h3>
<p>設定変更の前に設定ファイルをディレクトリ丸ごとバックアップする。</p>
<pre><code>cp -rp /etc/dovecot /root/dovecot.org
</code></pre>
<h3 id="各種設定を実施">2. 各種設定を実施</h3>
<p>DovecotはPostfix以上に設定ファイルが細分化されている。今回の修正対象ファイルを以下に記載する。</p>
<table>
<thead>
<tr>
<th style="width: 40%;">ファイル</th>
<th style="width: 60%;">内容</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>/etc/dovecot/dovecot.conf</code></td>
<td>メインの設定ファイル。プロトコルとしてIMAPを指定する(デフォルトではPOP3、IMAPの両方が動作する)。</td>
</tr>
<tr>
<td><code>/etc/dovecot/conf.d/10-auth.conf</code></td>
<td>認証方式を記載する。今回は平文による認証を無効化したうえで、CRAM-MD5による認証方式を用いる。</td>
</tr>
<tr>
<td><code>/etc/dovecot/conf.d/auth-passwdfile.conf.ext</code></td>
<td>認証する際のパスワードファイルの指定を行う。パスワード認証情報(<code>passdb</code>)及びユーザ認証情報(<code>userdb</code>)は、後程作成する<code>/etc/dovecot/users</code>ファイルを参照するよう設定する。</td>
</tr>
<tr>
<td><code>/etc/dovecot/conf.d/10-master.conf</code></td>
<td>PostfixがSASL認証で使用する際のUNIXソケットファイルのパスを指定する。</td>
</tr>
</tbody>
</table><p>それぞれのファイルの記載例を以下に記載する。</p>
<h4 id="etcdovecotdovecot.conf変更箇所抜粋"><code>/etc/dovecot/dovecot.conf</code>変更箇所抜粋</h4>
<pre><code>protocols = imap lmtp
</code></pre>
<h4 id="etcdovecotconf.d10-auth.conf変更箇所抜粋"><code>/etc/dovecot/conf.d/10-auth.conf</code>変更箇所抜粋</h4>
<pre><code>disable_plaintext_auth = yes
auth_mechanisms = cram-md5
#!include auth-system.conf.ext
!include auth-passwdfile.conf.ext
</code></pre>
<h4 id="etcdovecotconf.dauth-passwdfile.conf.ext変更箇所抜粋"><code>/etc/dovecot/conf.d/auth-passwdfile.conf.ext</code>変更箇所抜粋</h4>
<pre><code>passdb {
driver = passwd-file
args = scheme=CRAM-MD5 username_format=%u /etc/dovecot/users
}
userdb {
driver = passwd-file
args = username_format=%u /etc/dovecot/users
default_fields = uid=vmail gid=vmail home=/var/spool/virtual/%d/%n/Maildir
}
</code></pre>
<h4 id="etcdovecotconf.d10-master.conf変更箇所抜粋"><code>/etc/dovecot/conf.d/10-master.conf</code>変更箇所抜粋</h4>
<pre><code>service auth {
unix_listener /var/spool/postfix/private/auth {
mode = 0666
user = postfix
group = postfix
}
~(略)~
}
</code></pre>
<h3 id="ユーザ・パスワードファイルを作成">3. ユーザ・パスワードファイルを作成</h3>
<p>Dovecotのユーザ・パスワードファイルを作成する。パスワード情報は平文ではなくCRAM-MD5で暗号化されたものを記載する。CRAM-MD5の暗号化文字列の作成は以下コマンドで行う。</p>
<pre><code>doveadm pw -s CRAM-MD5 -p [パスワード文字列]
</code></pre>
<p>上記で作成したパスワード文字列を用いて、以下書式でユーザ・パスワードファイルを作成する。<strong>行末のコロン2つ(<code>::</code>)は必要となる</strong>ので省略しないこと。</p>
<pre><code>[ユーザ名]:[暗号化パスワード文字列]::
</code></pre>
<p>ユーザ・パスワードファイルの記載例を以下に記載する。</p>
<h4 id="etcdovecotusers"><code>/etc/dovecot/users</code></h4>
<pre><code>test01@example.com:{CRAM-MD5}dcbe8064d829ee98ad16817611150a123455fe1c9dfd79f5395be892f162bfd3::
test02@example.com:{CRAM-MD5}0a9a6905dfdefaf79e95b5a63274464123456166a2f27e593150e37ef2db952::
test11@example1.com:{CRAM-MD5}b71384fd047350e89123456a80ee9959dec89ff9766d75d45ab923792e44ea16::
</code></pre>
<h3 id="設定を反映">4. 設定を反映</h3>
<p>設定反映前に設定ファイルのチェックを行う。以下コマンドをすると各種設定値が羅列されるが、その際にエラーが表示されていなければ、設定値としては問題ない。</p>
<pre><code>doveconf -n
</code></pre>
<p>Dovecotに設定を反映するため再起動する。</p>
<pre><code>systemctl restart dovecot
systemctl enable dovecot
</code></pre>
<h2 id="動作確認">動作確認</h2>
<p>メールクライアントを使って確認することが手っ取り早い。</p>
<p>Windows環境であれば、<a href="https://portableapps.com/apps/internet/thunderbird_portable">Thunderbird Portable Edition</a>がインストール不要で使え、複数アカウント登録も簡単にできるのでお勧めとなる(ただし、容量は120MB程度あるので注意)。</p>
<p>今回はThunderbird Portable Editionを用いた確認手順を記載する。</p>
<h3 id="thunderbirdのアカウントの設定">1. Thunderbirdのアカウントの設定</h3>
<p>Thunderbirdを開き、「設定」→「アカウント設定」を開き、「アカウント操作」から「メールアカウントを追加」を選択する。</p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-FOlczYl6BCkt2B3WnK3gxVgjSeekmGS2TISbClK_rV5VfgfMQO3BUxDWg9Bq0VIFjlfPU--Cmo_bYFn66qcR4I2Dsaozg4odndiKlpsI3_yJzFOYKtrpvVJ-3UEWRAkUVUYO2sNsXUJwkeTJPnmWU-YRTtbsa5cHteeo9D9NGHbj3rtDT22JspjarEA/s389/018.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="280" data-original-width="389" height="288" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-FOlczYl6BCkt2B3WnK3gxVgjSeekmGS2TISbClK_rV5VfgfMQO3BUxDWg9Bq0VIFjlfPU--Cmo_bYFn66qcR4I2Dsaozg4odndiKlpsI3_yJzFOYKtrpvVJ-3UEWRAkUVUYO2sNsXUJwkeTJPnmWU-YRTtbsa5cHteeo9D9NGHbj3rtDT22JspjarEA/w400-h288/018.png" width="400" /></a></div>
<p>でアカウント追加を行う。その際に受信サーバー(IMAP)と送信サーバー(SMTP)の設定を以下の通り行う。</p>
<h4 id="受信サーバー">受信サーバー</h4>
<table>
<thead>
<tr>
<th style="width: 15%;">設定項目</th>
<th style="width: 25%;">設定値</th>
<th style="width: 60%;">説明</th>
</tr>
</thead>
<tbody>
<tr>
<td>プロトコル</td>
<td>IMAP</td>
<td>-</td>
</tr>
<tr>
<td>ホスト名</td>
<td>構築したサーバのIPアドレス</td>
<td>-</td>
</tr>
<tr>
<td>ポート番号</td>
<td>143</td>
<td>STARTTLSであれば143、SSL/TLSであれば993を選択する。</td>
</tr>
<tr>
<td>接続の保護</td>
<td>STARTTLS</td>
<td>Dovecotの<code>/etc/dovecot/conf.d/10-ssl.conf</code>にて<code>ssl = required</code>の設定がされていることから、STARTTLSまたはSSL/TLSのどちらかを選択する。ここまでの設定で明示的に設定はしていないが、DovecotはデフォルトでIMAPSの通信が可能な構成となっている。</td>
</tr>
<tr>
<td>認証方式</td>
<td>暗号化されたパスワード認証</td>
<td>CRAM-MD5で設定されているため、「暗号化されたパスワード認証」を指定する。</td>
</tr>
<tr>
<td>ユーザー名</td>
<td>Dovecotで設定したユーザ名を指定</td>
<td><code>/etc/dovecot/users</code>に記載したユーザ名を指定する。</td>
</tr>
</tbody>
</table><h4 id="送信サーバー">送信サーバー</h4>
<table>
<thead>
<tr>
<th style="width: 15%;">設定項目</th>
<th style="width: 25%;">設定値</th>
<th style="width: 60%;">説明</th>
</tr>
</thead>
<tbody>
<tr>
<td>ホスト名</td>
<td>構築したサーバのIPアドレス</td>
<td>-</td>
</tr>
<tr>
<td>ポート番号</td>
<td>25</td>
<td>-</td>
</tr>
<tr>
<td>接続の保護</td>
<td>なし</td>
<td>SSL/TLSの設定はしていないため、「なし」を指定する。</td>
</tr>
<tr>
<td>認証方式</td>
<td>暗号化されたパスワード認証</td>
<td>CRAM-MD5で設定されているため、「暗号化されたパスワード認証」を指定する。</td>
</tr>
<tr>
<td>ユーザー名</td>
<td>Dovecotで設定したユーザ名を指定</td>
<td><code>/etc/dovecot/users</code>に記載したユーザ名を指定する。</td>
</tr>
</tbody>
</table><p>図13</p>
<h3 id="設定時の警告を承認">2. 設定時の警告を承認</h3>
<p>アカウントの作成指示に以下のセキュリティ警告が表示される。いずれも、「確認」と「セキュリティ例外を承認」を選択する。</p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEggqlWjyx6imfo2Xdko-2O4-GzDqrSHatmzlWn_rNEqMweKoygU9_ltfit7ANquuQF3zS4hFzGF6KllRW9wt1AmYRNHw7tOC94lICW4o6bTSn9DZNKSH7UE7-ROxmh5nLzp03-LMwvTvBUD1GcTt9e-YONyDsPLoEfpNMNxHoEEkGWDCUKp7O5GmtcRBNg/s724/014.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="317" data-original-width="724" height="280" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEggqlWjyx6imfo2Xdko-2O4-GzDqrSHatmzlWn_rNEqMweKoygU9_ltfit7ANquuQF3zS4hFzGF6KllRW9wt1AmYRNHw7tOC94lICW4o6bTSn9DZNKSH7UE7-ROxmh5nLzp03-LMwvTvBUD1GcTt9e-YONyDsPLoEfpNMNxHoEEkGWDCUKp7O5GmtcRBNg/w640-h280/014.png" width="640" /></a></div><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEifSTNrjeM1WcKt-QyRXk11x0iJJGn1QPB0AzRDJTXt-6Jc-kHpC0Rni8MN5QNzfbp_6jsi6uP4bX9Ip5CjnrZ2K4Oy0eWU6b6V-NYlhNtxcCMz9JZd1OG-n6dOY5s0syE2Lo2TGxQfeEUJ4RKwcGesWqW-FUd61dB-lk36y9PbDxPwuSYqkHycJhgJwZE/s474/015.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="303" data-original-width="474" height="256" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEifSTNrjeM1WcKt-QyRXk11x0iJJGn1QPB0AzRDJTXt-6Jc-kHpC0Rni8MN5QNzfbp_6jsi6uP4bX9Ip5CjnrZ2K4Oy0eWU6b6V-NYlhNtxcCMz9JZd1OG-n6dOY5s0syE2Lo2TGxQfeEUJ4RKwcGesWqW-FUd61dB-lk36y9PbDxPwuSYqkHycJhgJwZE/w400-h256/015.png" width="400" /></a></div>
<h3 id="アカウント作成">4. アカウント作成</h3>
<p>設定が問題なければ「アカウント作成が完了しました」の画面が表示される。</p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1p_Wupxiwb3PptpyDqnHAUbd4W2aGMb66usn82n0vEY_aJKgDIlzE1O5T3inrptOCwcfxEImlsAC2sH7YJ7DRjkK7fpN_CZJ4YfKJPJhajt80WPVVQ9uKPnTbuwR54vNNzReqKOOWyli2QJTzjQGUBi1POpZnn95a6aLe-KoMMaUmfoxwtxgHPPPx9ls/s868/016.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="550" data-original-width="868" height="406" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1p_Wupxiwb3PptpyDqnHAUbd4W2aGMb66usn82n0vEY_aJKgDIlzE1O5T3inrptOCwcfxEImlsAC2sH7YJ7DRjkK7fpN_CZJ4YfKJPJhajt80WPVVQ9uKPnTbuwR54vNNzReqKOOWyli2QJTzjQGUBi1POpZnn95a6aLe-KoMMaUmfoxwtxgHPPPx9ls/w640-h406/016.png" width="640" /></a></div>
<h3 id="メール送受信テスト">3. メール送受信テスト</h3>
<p>同様の手順で複数アカウントを作成し、お互いでメールを送受信できることを確認できれば動作確認完了となる。</p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiCO5lWffCudQeFsEWcNBQKLRM5HMqIz9fU4Fhz2kEhSoXyDPZF0bJm9Een99jFmOAQyXBPk7K_sPaC7SFCByCVaUKipOstgf_8a7ppZ-qH6OHt29LHz60e9v_rVnHejvjLB4yl4UNkL0KhHCNle_65miAZAnW6pUXfEIybQEzBmA19P3ScHIy2tIUrKtk/s1025/019.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="454" data-original-width="1025" height="284" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiCO5lWffCudQeFsEWcNBQKLRM5HMqIz9fU4Fhz2kEhSoXyDPZF0bJm9Een99jFmOAQyXBPk7K_sPaC7SFCByCVaUKipOstgf_8a7ppZ-qH6OHt29LHz60e9v_rVnHejvjLB4yl4UNkL0KhHCNle_65miAZAnW6pUXfEIybQEzBmA19P3ScHIy2tIUrKtk/w640-h284/019.png" width="640" /></a></div>
<p>以上で、Postfix+DovecotでバーチャルドメインのIMAPメールサーバーを構築する手順は完了となる。</p>
tech-mmmmhttp://www.blogger.com/profile/01739191108051432575noreply@blogger.com0tag:blogger.com,1999:blog-7885523125238064555.post-25688994053215441622023-10-28T11:30:00.001+09:002023-10-28T11:30:00.145+09:00Pacemaker+Corosyncのハートビートのタイムアウト値を変更する<p>以前の記事にて、Pacemaker+Corosyncにてクラスターを構成し、NGINXなどを冗長化する手順を記載した。</p>
<ul>
<li><a href="https://tech-mmmm.blogspot.com/2020/07/centos-8-pacemakersquidunbound.html">CentOS 8 + PacemakerでSquidとUnboundを冗長化する</a></li>
<li><a href="https://tech-mmmm.blogspot.com/2022/06/nginxpacemaker.html">NGINXの負荷分散装置(ロードバランサ)をPacemakerで冗長化する</a></li>
</ul>
<p>今までは細かいチューニングはしてこなかったが、先日検証環境にて仮想マシンを3台同時にOSインストールを行ったところ、負荷上昇に伴い、<strong>Corosyncにて以下のようなハートビートの閾値超過の警告メッセージが表示</strong>された。</p>
<pre><code>Error in corosync.log : Aug 05 07:42:28 [2474] t3046ngnx
corosync warning [MAIN ]
Corosync main process was not scheduled (@1691188948066)
for 2737.8225 ms (threshold is 2400.0000 ms).
Consider token timeout increase.
</code></pre>
<p>要約すると、「<strong>Corosyncのハートビート(token)がタイムアウト値の閾値に近づいていることから、タイムアウト値の増加を検討せよ</strong>」、というメッセージとなる。</p>
<p>本記事では、<strong>Pacemaker+Corosyncのハートビートのタイムアウト値を変更する手順</strong>を記載する。</p>
<h2 id="環境">環境</h2>
<p>今回検証した環境は以下の通り。</p>
<ul>
<li>OS : AlmaLinux release 9.2</li>
<li>Pacemaker : version 2.1.5</li>
<li>Corosync : Corosync Cluster Engine, version ‘3.1.7’</li>
</ul>
<p>念のため、Pacemaker+Corosyncのクラスター構成図を以下に記載する。</p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi7gC0BwhsVDo8lVzVMQ9evE_8-9z7CjazGk-DCaGulbmD_M6xkZKEKZz9jGw_tomrFRouApHV100nHVV-sC9dCchV-16ZkHf2Y7zkH5HIkt9KZo4_fQeYFDGHx45wqvSPHu5KSxrxWDm73fy3SA7W_h2VyEkjGwQoaMywizdFaON6XPEYdFMC3YcDVtoA/s2323/NGINX_002.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1304" data-original-width="2323" height="360" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi7gC0BwhsVDo8lVzVMQ9evE_8-9z7CjazGk-DCaGulbmD_M6xkZKEKZz9jGw_tomrFRouApHV100nHVV-sC9dCchV-16ZkHf2Y7zkH5HIkt9KZo4_fQeYFDGHx45wqvSPHu5KSxrxWDm73fy3SA7W_h2VyEkjGwQoaMywizdFaON6XPEYdFMC3YcDVtoA/w640-h360/NGINX_002.png" width="640" /></a></div>
<h2 id="corosyncのハートビートのタイムアウト値を変更する手順-pcsコマンドで設定する場合">Corosyncのハートビートのタイムアウト値を変更する手順 (<code>pcs</code>コマンドで設定する場合)</h2>
<p><code>pcs</code>コマンドで以下の通り実行すれば、<code>corosync.conf</code>への設定追記から各ノードへの同期・反映まで、必要な作業はすべて実施してくれる。</p>
<p>最も簡単な手順となるため、通常は<code>pcs</code>コマンドで設定すれば問題ないだろう。</p>
<pre><code># pcs cluster config update totem token=5000
Sending updated corosync.conf to nodes...
t3045ngnx: Succeeded
t3046ngnx: Succeeded
t3045ngnx: Corosync configuration reloaded
</code></pre>
<h2 id="corosyncのハートビートのタイムアウト値を変更する手順-手動で設定する場合">Corosyncのハートビートのタイムアウト値を変更する手順 (手動で設定する場合)</h2>
<p>もし、<code>pcs</code>コマンドではなく手動で実施したい場合は本手順で実施する。</p>
<h3 id="設定前確認">1. 設定前確認</h3>
<p>Corosyncのハートビート間隔は、<code>token</code>という値で設定されている。現在の設定は<code>corosync-cmapctl</code>コマンドで確認できる。現在は、3000ミリ秒(3秒)で設定されていることがわかる。</p>
<pre><code># corosync-cmapctl | egrep 'token|consensus'
runtime.config.totem.cancel_token_hold_on_retransmit (u32) = 0
runtime.config.totem.consensus (u32) = 3600
runtime.config.totem.token (u32) = 3000 # <-★3000ミリ秒で設定(デフォルト)
runtime.config.totem.token_retransmit (u32) = 714
runtime.config.totem.token_retransmits_before_loss_const (u32) = 4
runtime.config.totem.token_warning (u32) = 75
</code></pre>
<p>タイムアウト値の修正は基本的に<code>token</code>のみで問題ないが、関連して自動計算される<code>consensus</code>という値もある。他にも<code>token</code>の値などから自動計算されるパラメータがあるが、本記事では設定しないので説明は割愛する。</p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>内容</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>token</code></td>
<td>ハートビート間隔(ミリ秒)。こちらの間隔の80%を超えると警告メッセージが表示される(そのため、前述したメッセージでは閾値が2400.0000 msと表示されている)。</td>
</tr>
<tr>
<td><code>consensus</code></td>
<td>新しいメンバーシップの設定を開始する前に合意が得られるまでの待ち時間。自動的に<code>token</code> * 1.2倍で設定される値ため、原則個別設定は不要。</td>
</tr>
</tbody>
</table><h3 id="corosync.confを修正">2. <code>corosync.conf</code>を修正</h3>
<p><code>/etc/corosync/corosync.conf</code>に対して、以下設定を追加する。</p>
<pre><code># vi /etc/corosync/corosync.conf
totem {
version: 2
cluster_name: clst-01
transport: knet
crypto_cipher: aes256
crypto_hash: sha256
cluster_uuid: 956d398413b349219b60cef218e681f9
token: 5000 # <-★追加
}
</code></pre>
<h3 id="クラスター間で設定を同期">3. クラスター間で設定を同期</h3>
<p>設定した<code>corosync.conf</code>の内容をクラスターに所属する全ノードに同期させる。</p>
<pre><code># pcs cluster sync
t3045ngnx: Succeeded
t3046ngnx: Succeeded
Warning: Corosync configuration has been synchronized, please reload corosync daemon using 'pcs cluster reload corosync' command.
</code></pre>
<h3 id="クラスターに設定を反映">4. クラスターに設定を反映</h3>
<p>同期した設定を反映させる。</p>
<pre><code># pcs cluster reload corosync
Corosync reloaded
</code></pre>
<h3 id="設定後確認">5. 設定後確認</h3>
<p>再度Corosyncの設定状況を確認すると、以下の通り<code>token</code>の設定が更新されていることがわかる。</p>
<pre><code># corosync-cmapctl | egrep 'token|consensus'
runtime.config.totem.cancel_token_hold_on_retransmit (u32) = 0
runtime.config.totem.consensus (u32) = 6000
runtime.config.totem.token (u32) = 5000 # <-★更新されている
runtime.config.totem.token_retransmit (u32) = 1190
runtime.config.totem.token_retransmits_before_loss_const (u32) = 4
runtime.config.totem.token_warning (u32) = 75
totem.token (u32) = 5000
</code></pre>
<p>以上で、Pacemaker+Corosyncのハートビートのタイムアウト値を変更する手順は完了となる。</p>
<h2 id="参考">参考</h2>
<ul>
<li><a href="https://www.suse.com/ja-jp/support/kb/doc/?id=000020513">How to setup corosync token and consensus in a cluster with more then 2 nodes using unicast (udpu) | Support | SUSE</a></li>
</ul>
tech-mmmmhttp://www.blogger.com/profile/01739191108051432575noreply@blogger.com0tag:blogger.com,1999:blog-7885523125238064555.post-23140251959262054972023-10-21T11:00:00.001+09:002023-10-21T11:00:00.143+09:00KubernetesのCNI「flannel」をバージョンアップする手順<p>先日Kubernetes環境をバージョンアップする手順を記載した。</p>
<ul>
<li><a href="https://tech-mmmm.blogspot.com/2023/07/kubernetes.html">Kubernetesバージョンアップ手順</a></li>
</ul>
<p>前回はKubernetes本体のバージョンアップ手順を記載したが、関連コンポーネントであるCRI (Container Runtime Interface)やCNI (Container Network Interface)のバージョンアップについては言及していなかった。</p>
<p>私の自宅Kubernetes環境ではCNIとしてflannelを用いている。本記事では<strong>KubernetesのCNI「flannel」をバージョンアップする手順</strong>を記載する。</p>
<h2 id="環境">環境</h2>
<p>以下に今回構築する各種ソフトウェアのバージョンを記載する。</p>
<ul>
<li>ホストOS : AlmaLinux 8.6</li>
<li>Kubernetes : v1.27.3</li>
<li>Docker : 23.0.5</li>
<li>CRI : cri-dockerd 0.3.4</li>
<li>CNI : flannel v0.21.5 -> v0.22.0</li>
</ul>
<p>今回の構成の概要図を以下に記載する。</p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiecng9EaVe6djj1Ci5cgOAkkFw5fNkHAlnVw3lmrVhwY2ZfOPY8KIWRq607KIGizKZledEC8jbmHaEMfNyxsk85ouH8-rkJAygFDW6ZFoVQqaJwyoF3Hk0VPE_PyZoF5nIty27IT-OCHn_xZv2JCKA28Ycz6shHGbKTRVJLag0UJaG-_vBON0q_66UWOo/s3077/CNI%E3%83%90%E3%83%BC%E3%82%B8%E3%83%A7%E3%83%B3%E3%82%A2%E3%83%83%E3%83%97.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1519" data-original-width="3077" height="316" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiecng9EaVe6djj1Ci5cgOAkkFw5fNkHAlnVw3lmrVhwY2ZfOPY8KIWRq607KIGizKZledEC8jbmHaEMfNyxsk85ouH8-rkJAygFDW6ZFoVQqaJwyoF3Hk0VPE_PyZoF5nIty27IT-OCHn_xZv2JCKA28Ycz6shHGbKTRVJLag0UJaG-_vBON0q_66UWOo/w640-h316/CNI%E3%83%90%E3%83%BC%E3%82%B8%E3%83%A7%E3%83%B3%E3%82%A2%E3%83%83%E3%83%97.png" width="640" /></a></div>
<h2 id="flannelバージョンアップ手順">flannelバージョンアップ手順</h2>
<h3 id="事前バージョン確認">1, 事前バージョン確認</h3>
<p>flannelのバージョンアップ前のバージョン確認をしておく。Dockerのコンテナイメージの情報から、今回のバージョンアップ前のバージョンは、v0.21.5となっていることがわかる。</p>
<pre><code># docker images | grep flannel
flannel/flannel v0.21.5 a6c0cb5dbd21 2 months ago 68.9MB
flannel/flannel-cni-plugin v1.1.2 7a2dcab94698 7 months ago 7.97MB
</code></pre>
<h3 id="最新のマニフェストファイルを適用">2. 最新のマニフェストファイルを適用</h3>
<p>flannelの最新のマニフェストファイルをダウンロードする。</p>
<pre><code># curl -LO https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml
</code></pre>
<p><code>kubectl apply</code>にて更新する。最下行の<code>daemonset.apps/kube-flannel-ds</code>が<code>configured</code>となっていれば、更新処理が実行される。</p>
<pre><code># kubectl apply -f kube-flannel.yml
namespace/kube-flannel unchanged
serviceaccount/flannel unchanged
clusterrole.rbac.authorization.k8s.io/flannel unchanged
clusterrolebinding.rbac.authorization.k8s.io/flannel unchanged
configmap/kube-flannel-cfg unchanged
daemonset.apps/kube-flannel-ds configured
</code></pre>
<h3 id="バージョンアップ完了まで待機">3. バージョンアップ完了まで待機</h3>
<p>マニフェストファイルを更新すると、ノード単位で順番にPodの再作成がされ自動的にローリングアップデートがされる。最終的に各ノードで動作していた<code>kube-flannel-ds</code>のPodは、新しいバージョンのPodとして起動する。</p>
<pre><code># kubectl get pod -n=kube-flannel -w
NAME READY STATUS RESTARTS AGE
kube-flannel-ds-5bqnn 1/1 Terminating 4 (8d ago) 60d
kube-flannel-ds-mghhs 1/1 Running 2 (35d ago) 60d
kube-flannel-ds-x9mzn 1/1 Running 2 (35d ago) 60d
kube-flannel-ds-5bqnn 0/1 Terminating 4 (8d ago) 60d
kube-flannel-ds-5bqnn 0/1 Terminating 4 (8d ago) 60d
kube-flannel-ds-5bqnn 0/1 Terminating 4 (8d ago) 60d
kube-flannel-ds-fgg2w 0/1 Pending 0 0s
kube-flannel-ds-fgg2w 0/1 Pending 0 0s
kube-flannel-ds-fgg2w 0/1 Init:0/2 0 0s
kube-flannel-ds-fgg2w 0/1 Init:1/2 0 1s
kube-flannel-ds-fgg2w 0/1 PodInitializing 0 7s
kube-flannel-ds-fgg2w 1/1 Running 0 8s
kube-flannel-ds-mghhs 1/1 Terminating 2 (35d ago) 60d
kube-flannel-ds-mghhs 0/1 Terminating 2 (35d ago) 60d
kube-flannel-ds-mghhs 0/1 Terminating 2 (35d ago) 60d
kube-flannel-ds-mghhs 0/1 Terminating 2 (35d ago) 60d
kube-flannel-ds-ztdg7 0/1 Pending 0 0s
kube-flannel-ds-ztdg7 0/1 Pending 0 0s
kube-flannel-ds-ztdg7 0/1 Init:0/2 0 0s
kube-flannel-ds-ztdg7 0/1 Init:1/2 0 1s
kube-flannel-ds-ztdg7 0/1 PodInitializing 0 6s
kube-flannel-ds-ztdg7 1/1 Running 0 7s
kube-flannel-ds-x9mzn 1/1 Terminating 2 (35d ago) 60d
kube-flannel-ds-x9mzn 0/1 Terminating 2 (35d ago) 60d
kube-flannel-ds-x9mzn 0/1 Terminating 2 (35d ago) 60d
kube-flannel-ds-x9mzn 0/1 Terminating 2 (35d ago) 60d
kube-flannel-ds-cz2q4 0/1 Pending 0 0s
kube-flannel-ds-cz2q4 0/1 Pending 0 0s
kube-flannel-ds-cz2q4 0/1 Init:0/2 0 0s
kube-flannel-ds-cz2q4 0/1 Init:1/2 0 1s
kube-flannel-ds-cz2q4 0/1 PodInitializing 0 7s
kube-flannel-ds-cz2q4 1/1 Running 0 9s
</code></pre>
<h3 id="事後バージョン確認">4. 事後バージョン確認</h3>
<p>flannelのバージョンアップ後のバージョン確認する。事前の確認においてv0.21.5だけだったコンテナイメージにv0.22.0が追加されている。</p>
<pre><code># docker images | grep flannel
flannel/flannel v0.22.0 38c11b8f4aa1 7 weeks ago 69.8MB
flannel/flannel v0.21.5 a6c0cb5dbd21 2 months ago 68.9MB
flannel/flannel-cni-plugin v1.1.2 7a2dcab94698 7 months ago 7.97MB
</code></pre>
<p>さらに、Podの詳細情報を確認すると、v0.22.0のコンテナイメージで起動していることが確認できる。</p>
<pre><code># kubectl describe pod kube-flannel-ds-cz2q4 -n=kube-flannel
Name: kube-flannel-ds-cz2q4
Namespace: kube-flannel
~(中略)~
Containers:
kube-flannel:
Container ID: docker://fcd1857a182c3622a9ba4bed91101e443d384705dcee03c97d0bf179704cec6d
Image: docker.io/flannel/flannel:v0.22.0 ★
Image ID: docker-pullable://flannel/flannel@sha256:5f83f1243057458e27249157394e3859cf31cc075354af150d497f2ebc8b54db
~(以下略)~
</code></pre>
<p>以上で、KubernetesのCNI「flannel」をバージョンアップする手順は完了となる。</p>
tech-mmmmhttp://www.blogger.com/profile/01739191108051432575noreply@blogger.com0tag:blogger.com,1999:blog-7885523125238064555.post-67071861362534061092023-10-14T11:00:00.002+09:002023-10-14T15:11:23.513+09:00KubernetesのCRI「cri-dockerd」をバージョンアップする手順<p>先日Kubernetes環境をバージョンアップする手順を記載した。</p>
<ul>
<li><a href="https://tech-mmmm.blogspot.com/2023/07/kubernetes.html">Kubernetesバージョンアップ手順</a></li>
</ul>
<p>前回はKubernetes本体のバージョンアップ手順を記載したが、関連コンポーネントであるCRI (Container Runtime Interface)やCNI (Container Network Interface)のバージョンアップについては言及していなかった。</p>
<p>私の自宅Kubernetes環境ではCRIとしてcri-dockerdを用いている。本記事では<strong>KubernetesのCRI「cri-dockerd」をバージョンアップする手順</strong>を記載する。</p>
<h2 id="環境">環境</h2>
<p>以下に今回構築する各種ソフトウェアのバージョンを記載する。</p>
<ul>
<li>ホストOS : AlmaLinux 8.6</li>
<li>Kubernetes : v1.27.3</li>
<li>Docker : 23.0.5</li>
<li>CRI : cri-dockerd 0.3.2 -> 0.3.4</li>
<li>CNI : flannel v0.22.0</li>
</ul>
<p>今回の構成の概要図を以下に記載する。</p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjGjqibKeL_0REKoijLI_wGcQcFVlUgchGsTvUAWtp9xl64oHUgMuDedhlnXUS3doj56yumZ8oEBUmCw8Oghl_ymHtY-H6CGruzTM8TBe11ULgteet0XVpR7HJeN8kS2uJfwU2rN8UpyCjX7pTeBRTwkz_jDR5ejn6yjdW92viUjsoh76B75XD0AhqG53I/s3077/CRI%E3%83%90%E3%83%BC%E3%82%B8%E3%83%A7%E3%83%B3%E3%82%A2%E3%83%83%E3%83%97.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1519" data-original-width="3077" height="316" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjGjqibKeL_0REKoijLI_wGcQcFVlUgchGsTvUAWtp9xl64oHUgMuDedhlnXUS3doj56yumZ8oEBUmCw8Oghl_ymHtY-H6CGruzTM8TBe11ULgteet0XVpR7HJeN8kS2uJfwU2rN8UpyCjX7pTeBRTwkz_jDR5ejn6yjdW92viUjsoh76B75XD0AhqG53I/w640-h316/CRI%E3%83%90%E3%83%BC%E3%82%B8%E3%83%A7%E3%83%B3%E3%82%A2%E3%83%83%E3%83%97.png" width="640" /></a></div>
<h2 id="cri-dockerdバージョンアップ手順">cri-dockerdバージョンアップ手順</h2>
<h3 id="事前バージョン確認">1. 事前バージョン確認</h3>
<p>cri-dockerdのバージョンアップ前のバージョン確認をしておく。今回のバージョンアップ前のバージョンは、0.3.2となっていることがわかる。</p>
<pre><code># cri-dockerd --buildinfo
Program: cri-dockerd
Version: 0.3.2 (HEAD)
GitCommit: HEAD
Go version: go1.20.4
</code></pre>
<h3 id="drain実行-podの退避・podの配置の禁止">2. drain実行 (Podの退避・Podの配置の禁止)</h3>
<p>一時的に<code>cri-dockerd</code>のサービス再起動が発生することから、念のためバージョンアップ対象ノードからPodを退避(drain)したのち、Podの配置を禁止(cordon)する。</p>
<pre><code># kubectl drain t1051kube --ignore-daemonsets
node/t1051kube cordoned
~(以下略)~
</code></pre>
<p>drainされると、ノードのステータスが<code>SchedulingDisabled</code>となる。</p>
<pre><code># kubectl get node
NAME STATUS ROLES AGE VERSION
t1051kube Ready,SchedulingDisabled control-plane 62d v1.27.3
t1052kube Ready control-plane 62d v1.27.3
t1053kube Ready control-plane 34d v1.27.3
</code></pre>
<h3 id="cri-dockerdのバージョンアップ">3. cri-dockerdのバージョンアップ</h3>
<p><code>git clone</code>にてcri-dockerdのリポジトリから必要なファイルを入手する。</p>
<pre><code># git clone https://github.com/Mirantis/cri-dockerd.git
</code></pre>
<p>cri-dockerdはGo言語にてビルドする必要があるため、そちらに必要となるファイルも入手する。</p>
<pre><code># wget https://storage.googleapis.com/golang/getgo/installer_linux
# chmod +x ./installer_linux
# ./installer_linux
</code></pre>
<p>cri-dockerdの公式手順に従い、再インストールを行う。</p>
<pre><code># cd cri-dockerd/
# mkdir -p bin
# /root/.go/bin/go build -o bin/cri-dockerd
# install -o root -g root -m 0755 bin/cri-dockerd /usr/local/bin/cri-dockerd
# cp -af packaging/systemd/* /etc/systemd/system
# sed -i -e 's,/usr/bin/cri-dockerd,/usr/local/bin/cri-dockerd,' /etc/systemd/system/cri-docker.service
</code></pre>
<p>最後にcri-dockerdのサービスを再起動する。</p>
<pre><code># systemctl daemon-reload
# systemctl restart cri-docker.service
</code></pre>
<h3 id="uncordon実行">4. uncordon実行</h3>
<p>バージョンアップが完了したので、対象ノードのcordon状態を解消するため、uncordonを実行する。</p>
<pre><code># kubectl uncordon t1051kube
</code></pre>
<p>最終的にノードがバージョンアップされた状態で<code>Ready</code>となった。</p>
<pre><code># kubectl get node
NAME STATUS ROLES AGE VERSION
t1051kube Ready control-plane 62d v1.27.3
t1052kube Ready control-plane 62d v1.27.3
t1053kube Ready control-plane 34d v1.27.3
</code></pre>
<h3 id="事後バージョン確認">5. 事後バージョン確認</h3>
<p>cri-dockerdのバージョンアップ後のバージョン確認する。事前の確認において0.3.2だったものが0.3.4となっていることがわかる。</p>
<pre><code># cri-dockerd --buildinfo
Program: cri-dockerd
Version: 0.3.4 (HEAD)
GitCommit: HEAD
Go version: go1.20.6
</code></pre>
<h3 id="手順1~5を残りのノードに対して繰り返す">6. 手順1~5を残りのノードに対して繰り返す</h3>
<p>残りのノードに対してもdrain、バージョンアップ、uncordonを繰り返しながらローリングアップデートを実行する。</p>
<p>以上で、KubernetesのCRI「cri-dockerd」をバージョンアップする手順は完了となる。</p>
tech-mmmmhttp://www.blogger.com/profile/01739191108051432575noreply@blogger.com0tag:blogger.com,1999:blog-7885523125238064555.post-77744090266293251182023-10-07T10:51:00.001+09:002023-10-07T10:51:00.143+09:00Ansible実行時の「Encryption using the Python crypt module is deprecated.」の警告メッセージを消す方法<p>ある日Ansibleを実行していると、以下の警告メッセージが表示された。</p>
<pre><code>[DEPRECATION WARNING]: Encryption using the Python crypt module is deprecated.
The Python crypt module is deprecated and will be removed from Python 3.13.
Install the passlib library for continued encryption functionality.
This feature will be removed in version 2.17.
Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.
</code></pre>
<p>本記事では、<strong>Ansibleの「Encryption using the Python crypt module is deprecated.」の警告メッセージを消す方法</strong>を記載する。</p>
<h2 id="環境">環境</h2>
<ul>
<li>OS : AlmaLinux 8.5</li>
<li>Ansible : 8.1.0 (ansible [core 2.15.1])</li>
<li>Python : 3.9.16</li>
</ul>
<h2 id="原因">原因</h2>
<p>以下2点つの条件が重なった際に警告メッセージが表示されるようだ。</p>
<ol>
<li>Playbookで<code>password_hash</code>といったパスワードをハッシュ化する構文を使用している。
<ul>
<li><code>password: "{{ 'P@ssw0rd!' | password_hash('sha512') }}"</code></li>
</ul>
</li>
<li>Pythonライブラリである<code>passlib</code>がインストールされていない。</li>
</ol>
<h2 id="解消方法">解消方法</h2>
<p>警告メッセージにも記載されている通り、Pythonライブラリである<code>passlib</code>をインストールすれば問題ない。</p>
<pre><code># python3 -m pip install passlib
WARNING: Running pip install with root privileges is generally not a good idea. Try `python3 -m pip install --user` instead.
Collecting passlib
Downloading passlib-1.7.4-py2.py3-none-any.whl (525 kB)
|████████████████████████████████| 525 kB 13.8 MB/s
Installing collected packages: passlib
Successfully installed passlib-1.7.4
</code></pre>
<p>簡単ではあるが、以上で完了となる。</p>
tech-mmmmhttp://www.blogger.com/profile/01739191108051432575noreply@blogger.com0tag:blogger.com,1999:blog-7885523125238064555.post-7716305625795505242023-09-30T11:30:00.001+09:002023-09-30T14:41:05.930+09:00Kubernetes Metrics Server導入手順 (kubectl topコマンドを使えるようにする)<p>Kubernetes環境のCPUやメモリリソースの使用率をKubernetes API経由で確認するための機能として、「Kubernetes Metrics Server」がある。</p>
<ul>
<li><a href="https://github.com/kubernetes-sigs/metrics-server">GitHub - kubernetes-sigs/metrics-server: Scalable and efficient source of container resource metrics for Kubernetes built-in autoscaling pipelines.</a></li>
</ul>
<p>Kubernetes Metrics Serverは、標準ではインストールされておらず使用できない。そのため、<code>kubectl top</code>コマンドでリソース情報を取得しようとしても、以下の通り"Metrics API not available"のエラーで失敗する。</p>
<pre><code># kubectl top node
error: Metrics API not available
# kubectl top pod -A
error: Metrics API not available
</code></pre>
<p>Kubernetes Metrics Serverは、マニフェストファイルをApplyすることで簡単に導入することができる。本記事では、<strong>Kubernetes Metrics Serverの導入手順</strong>を記載する。導入することで<code>kubectl top</code>コマンドを利用できるようにする。</p>
<h2 id="環境">環境</h2>
<p>環境は以下の通り。</p>
<ul>
<li>ホストOS : AlmaLinux 8.6</li>
<li>Kubernetes: v1.27.3</li>
<li>Kubernetes Metrics Server: v0.6.3 (2023/7/16導入)</li>
</ul>
<h2 id="kubernetes-metrics-server導入手順">Kubernetes Metrics Server導入手順</h2>
<h3 id="インストール用マニフェストファイルのダウンロード">1. インストール用マニフェストファイルのダウンロード</h3>
<p>Kubernetes Metrics Serverはマニフェストファイルを用いることでインストールできる。公式手順は直接<code>kubectl apply [URL]</code>コマンドを実行しているが、今回は次の手順で一部マニフェストファイルを編集をするため、先に<code>curl</code>コマンドでダウンロードを行う。</p>
<pre><code>#curl -LO https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
# ls -l
-rw-r--r-- 1 root root 4186 7月 16 17:20 components.yaml
</code></pre>
<h3 id="マニフェストファイルを編集">2. マニフェストファイルを編集</h3>
<p>Kubernetes Metrics ServerへはHTTPSによる通信にて接続を行うが、その際にSSL証明書の検証が動作し、検証に失敗すると正常にリソース情報を取得することができない。</p>
<p>そこで、<code>--kubelet-insecure-tls</code>のオプションを追加し、証明書の検証を行わないよう設定する。</p>
<h4 id="components.yaml"><code>components.yaml</code></h4>
<pre><code>~(中略)~
strategy:
rollingUpdate:
maxUnavailable: 0
template:
metadata:
labels:
k8s-app: metrics-server
spec:
containers:
- args:
- --cert-dir=/tmp
- --secure-port=4443
- --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname
- --kubelet-use-node-status-port
- --metric-resolution=15s
- --kubelet-insecure-tls # <-★追加
~(以下略)~
</code></pre>
<h3 id="マニフェストファイルをapply">3. マニフェストファイルをapply</h3>
<p>修正したマニフェストファイルをapplyする。</p>
<pre><code># kubectl apply -f components.yaml
serviceaccount/metrics-server created
clusterrole.rbac.authorization.k8s.io/system:aggregated-metrics-reader created
clusterrole.rbac.authorization.k8s.io/system:metrics-server created
rolebinding.rbac.authorization.k8s.io/metrics-server-auth-reader created
clusterrolebinding.rbac.authorization.k8s.io/metrics-server:system:auth-delegator created
clusterrolebinding.rbac.authorization.k8s.io/system:metrics-server created
service/metrics-server created
deployment.apps/metrics-server created
apiservice.apiregistration.k8s.io/v1beta1.metrics.k8s.io created
</code></pre>
<h3 id="pod及びサービスリソースの起動確認">4. Pod及びサービスリソースの起動確認</h3>
<p>10秒ほど経過してから確認すると、Podとサービスリソースが正常に展開されているはずだ。</p>
<pre><code># kubectl get pod -n=kube-system
NAME READY STATUS RESTARTS AGE
~(中略)~
metrics-server-7db4fb59f9-skc7s 1/1 Running 0 144m
# kubectl get service -n=kube-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP,9153/TCP 53d
metrics-server ClusterIP 10.107.188.51 <none> 443/TCP 3h2m
</code></pre>
<p>もし、<strong>PodのREADYが0/1などになっている場合は正常にコンテナが起動していない可能性がある</strong>ため、Podのログを確認して原因調査が必要となる。例えば、<code>--kubelet-insecure-tls</code>オプションを付与しておらず証明書の検証に失敗した場合は、以下のような"statuscode: 500"のエラーが表示される。</p>
<pre><code># kubectl describe pod metrics-server-7b4c4d4bfd-tbctq -n=kube-system
Name: metrics-server-7b4c4d4bfd-tbctq
Namespace: kube-system
~(中略)~
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 5m48s default-scheduler Successfully assigned kube-system/metrics-server-7b4c4d4bfd-tbctq to t3052kube
Normal Pulled 5m48s kubelet Container image "registry.k8s.io/metrics-server/metrics-server:v0.6.3" already present on machine
Normal Created 5m48s kubelet Created container metrics-server
Normal Started 5m48s kubelet Started container metrics-server
Warning Unhealthy 38s (x33 over 5m28s) kubelet Readiness probe failed: HTTP probe failed with statuscode: 500
↑★"statuscode: 500"のエラー
</code></pre>
<h3 id="kubectl-topコマンドで動作確認">5. <code>kubectl top</code>コマンドで動作確認</h3>
<p><code>kubectl top</code>コマンドでノードとPodのリソース取得ができることの確認をしてみよう。</p>
<h4 id="ノードの場合">ノードの場合</h4>
<pre><code># kubectl top node
NAME CPU(cores) CPU% MEMORY(bytes) MEMORY%
t3051kube 121m 3% 2459Mi 67%
t3052kube 90m 2% 1076Mi 29%
t3053kube 105m 2% 2470Mi 68%
</code></pre>
<h4 id="podの場合">Podの場合</h4>
<pre><code>[root@t3051kube metrics-server]# kubectl top pod -A
NAMESPACE NAME CPU(cores) MEMORY(bytes)
~(中略)~
mynamespace almalinux-postfix-7b4577c6bc-fq578 1m 36Mi
mynamespace almalinux-postfix-7b4577c6bc-hds6v 1m 43Mi
mynamespace almalinux-postfix-7b4577c6bc-mtrnp 1m 42Mi
mynamespace almalinux-squid-d66588dbb-g6tn6 1m 200Mi
mynamespace almalinux-squid-d66588dbb-m5fff 1m 279Mi
mynamespace almalinux-squid-d66588dbb-t9lg6 1m 266Mi
mynamespace almalinux-unbound-66c9746bff-92htn 0m 42Mi
mynamespace almalinux-unbound-66c9746bff-f5gmk 0m 37Mi
mynamespace almalinux-unbound-66c9746bff-rnw8m 0m 40Mi
</code></pre>
<p>以上で、Kubernetes Metrics Serverの導入手順は終了となる。</p>
tech-mmmmhttp://www.blogger.com/profile/01739191108051432575noreply@blogger.com0tag:blogger.com,1999:blog-7885523125238064555.post-88142503788615176772023-09-16T11:00:00.026+09:002023-09-16T16:41:29.722+09:00Pgpool-IIを使ってフェイルオーバーとオンラインリカバリを実行する<p>前回、Pgpool-IIを使ってPostgreSQLのストリーミングレプリケーション構成を管理するための構築手順を記載した。</p>
<ul>
<li><a href="https://tech-mmmm.blogspot.com/2023/09/pgpool-iipostgresql.html">Pgpool-IIを使ってPostgreSQL (ストリーミングレプリケーション構成) を管理する</a></li>
</ul>
<p>Pgpool-IIでは、定期的にPostgreSQLに対してヘルスチェックを実行しており、マスターのDB停止を契機としてフェイルオーバー(スタンバイDBをマスターDBに昇格)を実行できる。</p>
<p>また、フェイルオーバー後に旧マスターをスタンバイDBとしてストリーミングレプリケーション構成に復旧させることもできる。この作業は、マスターDBのI/Oを停止させることなく実行できることから「オンラインリカバリ」と呼ばれる。</p>
<p>Pgpool-IIのフェイルオーバーやオンラインリカバリは、スクリプトにて実装される。本記事では、<strong>Pgpool-IIを使ってフェイルオーバーとオンラインリカバリを実行するための手順</strong>を記載する。</p>
<h2 id="環境">環境</h2>
<p>OSはRHEL互換OSであるAlmaLinuxを利用し、パッケージ提供されているPostgreSQLを利用する。</p>
<ul>
<li>OS : AlmaLinux release 8.8</li>
<li>PostgreSQL : 15.2</li><li>Pgpool-II : 4.4.4</li>
</ul>
<p>マスターとスタンバイの2台にPostgreSQLをインストールし、ストリーミングレプリケーションを構成する。ホスト名やIPアドレスは以下図を参照いただきたい。</p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigfLBFtHIEBwufD_QXu6YiGvxUz_LL4BFS8Fj2U6RrhUsfiYuyQnXxwOwktWeqeKmiWsPGjHngXAEa1Fz1shJCBi28v2kw1ty3Xz1Zy2rit5SaGnTU_bKOHAvHWOuiVU8sU7R3g5b9vSmpFhq5qc-4GzI9ngebZMKUSwslViWKWi52B9xAsPsR-eCdhz8/s2450/pgpool001.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1956" data-original-width="2450" height="510" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigfLBFtHIEBwufD_QXu6YiGvxUz_LL4BFS8Fj2U6RrhUsfiYuyQnXxwOwktWeqeKmiWsPGjHngXAEa1Fz1shJCBi28v2kw1ty3Xz1Zy2rit5SaGnTU_bKOHAvHWOuiVU8sU7R3g5b9vSmpFhq5qc-4GzI9ngebZMKUSwslViWKWi52B9xAsPsR-eCdhz8/w640-h510/pgpool001.png" width="640" /></a></div>
<p>今回はPgpool-II導入サーバ、マスターDBサーバ、スタンバイDBサーバで実施する作業が異なる。そのため、本記事で記載するプロンプトを以下の通り記載し、作業対象が判別できるようにした。</p>
<table>
<thead>
<tr>
<th>プロンプト</th>
<th>ユーザー</th>
<th>対象</th>
</tr>
</thead>
<tbody>
<tr>
<td>[Pgpool]#</td>
<td>root</td>
<td>Pgpool-II導入サーバのみ実施</td>
</tr>
<tr>
<td>[Master/Standby]#</td>
<td>root</td>
<td>マスターとスタンバイ両方で実施</td>
</tr>
<tr>
<td>[Master]#</td>
<td>root</td>
<td>マスターのみ実施</td>
</tr>
<tr>
<td>[Standby]#</td>
<td>root</td>
<td>スタンバイのみ実施</td>
</tr>
<tr>
<td>[Pgpool]$</td>
<td>postgres</td>
<td>Pgpool-II導入サーバのみ実施</td>
</tr>
<tr>
<td>[Master/Standby]$</td>
<td>postgres</td>
<td>マスターとスタンバイ両方で実施</td>
</tr>
<tr>
<td>[Master]$</td>
<td>postgres</td>
<td>マスターのみ実施</td>
</tr>
<tr>
<td>[Standby]$</td>
<td>postgres</td>
<td>スタンバイのみ実施</td>
</tr>
</tbody>
</table><h2 id="スクリプト配置">スクリプト配置</h2>
<p>Pgpool-IIのサンプルスクリプトは<code>/etc/pgpool-II/sample_scripts/</code>ディレクトリに存在する。そちらを使用してもよいが、不要な処理を削除してシンプルにしたいため、サンプルスクリプトは参考にしつつオリジナルのスクリプトを作成した。</p>
<p>以下サンプルスクリプトの一覧となる。</p>
<pre><code>[Pgpool]$ ls -1 /etc/pgpool-II/sample_scripts/
aws_eip_if_cmd.sh.sample
aws_rtb_if_cmd.sh.sample
escalation.sh.sample
failover.sh.sample
follow_primary.sh.sample
pgpool_remote_start.sample
recovery_1st_stage.sample
replication_mode_recovery_1st_stage.sample
replication_mode_recovery_2nd_stage.sample
</code></pre>
<h3 id="フェイルオーバー用スクリプトの作成・配置">1. フェイルオーバー用スクリプトの作成・配置</h3>
<p>フェイルオーバー用スクリプトの処理の流れを記載する。</p>
<ol>
<li>引数を変数に代入する。</li>
<li>実行ユーザーをpostgresとして設定する。</li>
<li>昇格対象となるスタンバイDB(<code>NEW_MAIN_NODE_HOST</code>)にSSH接続するための、SSHコマンド文を作成する。</li>
<li>スタンバイDBをマスターDBとして昇格させる。</li>
<li><code>synchronous_standby_names='*'</code>が設定されている場合、レプリケーション完了までDBが応答を返すことができず、実質更新ができなくなる。そのため、<code>synchronous_standby_names=''</code>のように空白設定に変更する。</li>
<li>設定反映のため、昇格したDBの設定をリロードする。</li>
</ol>
<p>実際のスクリプトを以下に記載する。本スクリプトは、Pgpool-II導入サーバの<code>/var/lib/pgsql</code>に配置する。</p>
<h4 id="failover.sh"><code>failover.sh</code></h4>
<pre><code>#!/bin/bash
# This script is run by failover_command.
set -eu
set -o xtrace
# Special values:
# 1) %d = failed node id
# 2) %h = failed node hostname
# 3) %p = failed node port number
# 4) %D = failed node database cluster path
# 5) %m = new main node id
# 6) %H = new main node hostname
# 7) %M = old main node id
# 8) %P = old primary node id
# 9) %r = new main port number
# 10) %R = new main database cluster path
# 11) %N = old primary node hostname
# 12) %S = old primary node port number
# 13) %% = '%' character
FAILED_NODE_ID="$1"
FAILED_NODE_HOST="$2"
FAILED_NODE_PORT="$3"
FAILED_NODE_PGDATA="$4"
NEW_MAIN_NODE_ID="$5"
NEW_MAIN_NODE_HOST="$6"
OLD_MAIN_NODE_ID="$7"
OLD_PRIMARY_NODE_ID="$8"
NEW_MAIN_NODE_PORT="$9"
NEW_MAIN_NODE_PGDATA="${10}"
OLD_PRIMARY_NODE_HOST="${11}"
OLD_PRIMARY_NODE_PORT="${12}"
POSTGRESQL_STARTUP_USER=postgres
SSH_KEY_FILE=id_rsa
SSH_OPTIONS="-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i ~/.ssh/${SSH_KEY_FILE}"
SSH_CMD="ssh -T ${SSH_OPTIONS} ${POSTGRESQL_STARTUP_USER}@${NEW_MAIN_NODE_HOST}"
${SSH_CMD} /usr/bin/pg_ctl promote -D ${NEW_MAIN_NODE_PGDATA} -w
${SSH_CMD} "sed -ie \"s/^synchronous_standby_names = '\*'/synchronous_standby_names = ''/g\" ${NEW_MAIN_NODE_PGDATA}/postgresql.conf"
${SSH_CMD} /usr/bin/pg_ctl reload -D ${NEW_MAIN_NODE_PGDATA} -w
exit 0
</code></pre>
<h3 id="オンラインリカバリ用スクリプトの作成・配置">2. オンラインリカバリ用スクリプトの作成・配置</h3>
<p>オンラインリカバリ用スクリプトの処理の流れを記載する。</p>
<ol>
<li>引数を変数に代入する。</li>
<li>レプリケーション用のDBユーザーをdbrepl、実行ユーザーをpostgresとして設定する。</li>
<li>リカバリ対象となるスタンバイDB(<code>DEST_NODE_HOST</code>)にSSH接続するための、SSHコマンド文を作成する。</li>
<li>スタンバイDBのデータ領域を削除する。</li>
<li><code>pg_basebackup</code>コマンドを使って、マスターDBのデータをスタンバイDBにコピー(ベースバックアップ)を行う。</li>
<li>スタンバイDBとして動作させるため、<code>standby.signal</code>ファイルを生成する。</li>
<li><code>postgresql.conf</code>に含まれるスタンバイDBのホスト名をマスターDBのホスト名に入れ替える。</li>
<li><code>application_name</code>の設定値をスタンバイDBのホスト名に変更する。</li>
<li>マスターDBにてフェイルオーバー時に変更した<code>synchronous_standby_names</code>の設定値を<code>synchronous_standby_names='*'</code>に戻し、レプリケーションを再開する。</li>
<li>設定反映のため、昇格したDBの設定をリロードする。</li>
</ol>
<p>以下のスクリプトをPgpool-IIの管理対象となる<strong>DBサーバーのデータ領域(通常は<code>/var/lib/pgsql/data</code>)に配置</strong>する。</p>
<h4 id="replication_mode_recovery_1st_stage"><code>replication_mode_recovery_1st_stage</code></h4>
<pre><code>#!/bin/bash
# This script is executed by "recovery_1st_stage" to recovery a Standby node.
set -eu
set -o xtrace
MAIN_NODE_PGDATA="$1" # main node dabatase cluster path
DEST_NODE_HOST="$2" # hostname of the DB node to be recovered
DEST_NODE_PGDATA="$3" # database cluster path of the DB node to be recovered
MAIN_NODE_PORT="$4" # main node port number
DEST_NODE_ID="$5" # node id of the DB node to be recovered
DEST_NODE_PORT="$6" # port number of the DB node to be recovered
MAIN_NODE_HOST="$7" # main node hostname
REPLUSER=dbrepl
POSTGRESQL_STARTUP_USER=postgres
SSH_KEY_FILE=id_rsa
SSH_OPTIONS="-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i ~/.ssh/${SSH_KEY_FILE}"
SSH_CMD="ssh -T ${SSH_OPTIONS} ${POSTGRESQL_STARTUP_USER}@${DEST_NODE_HOST}"
# Standby側(オンラインリカバリされる側)の処理
${SSH_CMD} "[ -d ${DEST_NODE_PGDATA} ] && rm -rf ${DEST_NODE_PGDATA}"
${SSH_CMD} "/usr/bin/pg_basebackup -D ${DEST_NODE_PGDATA} -h ${MAIN_NODE_HOST} -X stream -c fast -U ${REPLUSER} -p ${MAIN_NODE_PORT} -w"
${SSH_CMD} "touch ${DEST_NODE_PGDATA}/standby.signal"
${SSH_CMD} "sed -ie \"s#${DEST_NODE_HOST}#${MAIN_NODE_HOST}#g\" ${DEST_NODE_PGDATA}/postgresql.conf"
${SSH_CMD} "sed -ie \"s#application_name=${MAIN_NODE_HOST}#application_name=${DEST_NODE_HOST}#g\" ${DEST_NODE_PGDATA}/postgresql.conf"
# Master側の処理
sed -ie "s/^synchronous_standby_names = ''/synchronous_standby_names = '\*'/g" ${MAIN_NODE_PGDATA}/postgresql.conf
/usr/bin/pg_ctl reload -D ${MAIN_NODE_PGDATA} -w
exit 0
</code></pre>
<h3 id="オンラインリカバリ後のスタンバイdb起動スクリプトの作成・配置">3. オンラインリカバリ後のスタンバイDB起動スクリプトの作成・配置</h3>
<p>オンラインリカバリ後にスタンバイDB起動は、別のスクリプトとして用意する必要がある。本スクリプトの処理の流れを記載する。</p>
<ol>
<li>引数を変数に代入する。</li>
<li>実行ユーザーをpostgresとして設定する。</li>
<li>リカバリ対象となるスタンバイDB(<code>DEST_NODE_HOST</code>)にSSH接続するための、SSHコマンド文を作成する。</li>
<li>スタンバイDB起動する。</li>
</ol>
<p>以下のスクリプトをPgpool-IIの管理対象となる<strong>DBサーバーのデータ領域(通常は<code>/var/lib/pgsql/data</code>)に配置</strong>する。</p>
<h4 id="pgpool_remote_start"><code>pgpool_remote_start</code></h4>
<pre><code>#!/bin/bash
# This script is run after recovery_1st_stage to start Standby node.
set -eu
set -o xtrace
DEST_NODE_HOST="$1"
DEST_NODE_PGDATA="$2"
POSTGRESQL_STARTUP_USER=postgres
SSH_KEY_FILE=id_rsa
SSH_OPTIONS="-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i ~/.ssh/${SSH_KEY_FILE}"
SSH_CMD="ssh -T ${SSH_OPTIONS} ${POSTGRESQL_STARTUP_USER}@${DEST_NODE_HOST}"
# DB起動
${SSH_CMD} "/usr/bin/pg_ctl start -D ${DEST_NODE_PGDATA} -w -l /dev/null"
exit 0
</code></pre>
<h2 id="フェイルオーバー確認">フェイルオーバー確認</h2>
<h3 id="事前状態確認">1. 事前状態確認</h3>
<p>それでは実際にフェイルオーバーをさせてみる。まずは、Pgpool-IIの状態を確認する。node_id: 0がprimary、node_id: 1がstandbyとなっている。</p>
<pre><code>[Pgpool]$ psql -p 9999 -x -c "show pool_nodes"
-[ RECORD 1 ]----------+--------------------
node_id | 0
hostname | t1117psgl
port | 5432
status | up
pg_status | up
lb_weight | 0.500000
role | primary
pg_role | primary
select_cnt | 0
load_balance_node | false
replication_delay | 0
replication_state |
replication_sync_state |
last_status_change | 2023-08-26 23:31:00
-[ RECORD 2 ]----------+--------------------
node_id | 1
hostname | t1118psgl
port | 5432
status | up
pg_status | up
lb_weight | 0.500000
role | standby
pg_role | standby
select_cnt | 0
load_balance_node | true
replication_delay | 0
replication_state | streaming
replication_sync_state | sync
last_status_change | 2023-08-26 23:31:00
</code></pre>
<h3 id="マスター側のdbを停止">2. マスター側のDBを停止</h3>
<p>マスターDBとなるnode_id: 0のDBを停止する。</p>
<pre><code>[Master]# systemctl stop postgresql
</code></pre>
<h3 id="実行後ログ確認">3. 実行後ログ確認</h3>
<p>Pgpool-IIのログ(<code>/var/log/pgpool_log/pgpool-*.log</code>)に以下の通り出力される。<code>failover.sh</code>実行ログがそのまま出力されていることがわかる。</p>
<pre><code>[Pgpool]$ cat /var/log/pgpool_log/pgpool-Sun.log
~(中略)~
2023-08-27 11:21:30.902: main pid 8071: LOG: === Starting degeneration. shutdown host t1117psgl(5432) ===
2023-08-27 11:21:30.903: main pid 8071: LOG: Restart all children
2023-08-27 11:21:30.903: main pid 8071: LOG: execute command: /var/lib/pgsql/failover.sh 0 t1117psgl 5432 /var/lib/pgsql/data 1 t1118psgl 0 0 5432 /var/lib/pgsql/data t1117psgl 5432
+ FAILED_NODE_ID=0
+ FAILED_NODE_HOST=t1117psgl
+ FAILED_NODE_PORT=5432
+ FAILED_NODE_PGDATA=/var/lib/pgsql/data
+ NEW_MAIN_NODE_ID=1
+ NEW_MAIN_NODE_HOST=t1118psgl
+ OLD_MAIN_NODE_ID=0
+ OLD_PRIMARY_NODE_ID=0
+ NEW_MAIN_NODE_PORT=5432
+ NEW_MAIN_NODE_PGDATA=/var/lib/pgsql/data
+ OLD_PRIMARY_NODE_HOST=t1117psgl
+ OLD_PRIMARY_NODE_PORT=5432
+ POSTGRESQL_STARTUP_USER=postgres
+ SSH_KEY_FILE=id_rsa
+ SSH_OPTIONS='-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i ~/.ssh/id_rsa'
+ SSH_CMD='ssh -T -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i ~/.ssh/id_rsa postgres@t1118psgl'
+ ssh -T -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i '~/.ssh/id_rsa' postgres@t1118psgl /usr/bin/pg_ctl promote -D /var/lib/pgsql/data -w
Warning: Permanently added 't1118psgl,192.168.11.118' (ECDSA) to the list of known hosts.
サーバーの昇格を待っています....完了
サーバーは昇格しました
+ ssh -T -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i '~/.ssh/id_rsa' postgres@t1118psgl 'sed -ie "s/^synchronous_standby_names = '\''\*'\''/synchronous_standby_names = '\'''\''/g" /var/lib/pgsql/data/postgresql.conf'
Warning: Permanently added 't1118psgl,192.168.11.118' (ECDSA) to the list of known hosts.
+ ssh -T -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i '~/.ssh/id_rsa' postgres@t1118psgl /usr/bin/pg_ctl reload -D /var/lib/pgsql/data -w
Warning: Permanently added 't1118psgl,192.168.11.118' (ECDSA) to the list of known hosts.
サーバーにシグナルを送信しました
+ exit 0
2023-08-27 11:21:31.954: main pid 8071: LOG: find_primary_node_repeatedly: waiting for finding a primary node
2023-08-27 11:21:31.962: main pid 8071: LOG: find_primary_node: primary node is 1
2023-08-27 11:21:31.962: main pid 8071: LOG: failover: set new primary node: 1
2023-08-27 11:21:31.962: main pid 8071: LOG: failover: set new main node: 1
2023-08-27 11:21:31.965: main pid 8071: LOG: === Failover done. shutdown host t1117psgl(5432) ===
</code></pre>
<h3 id="事後状態確認">4. 事後状態確認</h3>
<p>Pgpool-IIにてフェイルオーバー後の状態確認を行う。以下の通り、node_id: 1がprimaryに昇格し、node_id: 0がstandbyかつステータスがdownとなっていることが確認できる。</p>
<pre><code>[Pgpool]$ psql -p 9999 -x -c "show pool_nodes"
-[ RECORD 1 ]----------+--------------------
node_id | 0
hostname | t1117psgl
port | 5432
status | down ←★downに変化している
pg_status | down ←★downに変化している
lb_weight | 0.500000
role | standby
pg_role | unknown ←★unknownになっている
select_cnt | 0
load_balance_node | false
replication_delay | 0
replication_state |
replication_sync_state |
last_status_change | 2023-08-27 11:21:31
-[ RECORD 2 ]----------+--------------------
node_id | 1
hostname | t1118psgl
port | 5432
status | up
pg_status | up
lb_weight | 0.500000
role | primary ←★マスター(=primary)に昇格
pg_role | primary ←★マスター(=primary)に昇格
select_cnt | 0
load_balance_node | true
replication_delay | 0
replication_state |
replication_sync_state |
last_status_change | 2023-08-27 11:21:31
</code></pre>
<h2 id="オンラインリカバリ">オンラインリカバリ</h2>
<h3 id="オンラインリカバリ実行">1. オンラインリカバリ実行</h3>
<p>オンラインリカバリは<code>pcp_recovery_node -n [リカバリ対象のDBのnode_id]</code>で実行する。今回は、node_id: 0をスタンバイDBとして復旧させることから、以下の通りコマンドを実行する。<code>Command Successful</code>と表示されれば、オンラインリカバリ成功となる。</p>
<pre><code>[Pgpool]$ pcp_recovery_node -n 0
Password:
pcp_recovery_node -- Command Successful
</code></pre>
<h3 id="実行後ログ確認-1">2. 実行後ログ確認</h3>
<p>マスター側のPostgreSQLのログに、以下の通りスクリプト実行結果が出力される。</p>
<pre><code>[Master]$ cat /var/lib/pgsql/data/log/postgresql-Sun.log
~(中略)~
2023-08-27 11:23:07.101 JST [7329] LOG: checkpoint complete: wrote 957 buffers (5.8%); 0 WAL file(s) added, 0 removed, 0 recycled; write=95.410 s, sync=0.063 s, total=95.475 s; sync files=252, longest=0.063 s, average=0.001 s; distance=16036 kB, estimate=16662 kB
+ MAIN_NODE_PGDATA=/var/lib/pgsql/data
+ DEST_NODE_HOST=t1117psgl
+ DEST_NODE_PGDATA=/var/lib/pgsql/data
+ MAIN_NODE_PORT=5432
+ DEST_NODE_ID=0
+ DEST_NODE_PORT=5432
+ MAIN_NODE_HOST=t1118psgl
+ REPLUSER=dbrepl
+ POSTGRESQL_STARTUP_USER=postgres
+ SSH_KEY_FILE=id_rsa
+ SSH_OPTIONS='-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i ~/.ssh/id_rsa'
+ SSH_CMD='ssh -T -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i ~/.ssh/id_rsa postgres@t1117psgl'
+ ssh -T -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i '~/.ssh/id_rsa' postgres@t1117psgl '[ -d /var/lib/pgsql/data ] && rm -rf /var/lib/pgsql/data'
Warning: Permanently added 't1117psgl,192.168.11.117' (ECDSA) to the list of known hosts.
+ ssh -T -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i '~/.ssh/id_rsa' postgres@t1117psgl '/usr/bin/pg_basebackup -D /var/lib/pgsql/data -h t1118psgl -X stream -c fast -U dbrepl -p 5432 -w'
Warning: Permanently added 't1117psgl,192.168.11.117' (ECDSA) to the list of known hosts.
2023-08-27 11:23:18.370 JST [7329] LOG: checkpoint starting: immediate force wait
2023-08-27 11:23:18.388 JST [7329] LOG: checkpoint complete: wrote 4 buffers (0.0%); 0 WAL file(s) added, 0 removed, 0 recycled; write=0.001 s, sync=0.001 s, total=0.019 s; sync files=2, longest=0.001 s, average=0.001 s; distance=16383 kB, estimate=16634 kB
+ ssh -T -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i '~/.ssh/id_rsa' postgres@t1117psgl 'touch /var/lib/pgsql/data/standby.signal'
Warning: Permanently added 't1117psgl,192.168.11.117' (ECDSA) to the list of known hosts.
+ ssh -T -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i '~/.ssh/id_rsa' postgres@t1117psgl 'sed -ie "s#^primary_conninfo =.*#primary_conninfo = '\''application_name=t1117psgl user=dbrepl passfile='\'''\''/var/lib/pgsql/.pgpass'\'''\'' host=t1118psgl port=5432'\''#g" /var/lib/pgsql/data/postgresql.conf'
Warning: Permanently added 't1117psgl,192.168.11.117' (ECDSA) to the list of known hosts.
+ sed -ie 's/^synchronous_standby_names = '\'''\''/synchronous_standby_names = '\''\*'\''/g' /var/lib/pgsql/data/postgresql.conf
+ /usr/bin/pg_ctl reload -D /var/lib/pgsql/data -w
server signaled
2023-08-27 11:23:18.833 JST [7327] LOG: received SIGHUP, reloading configuration files
+ exit 0
2023-08-27 11:23:18.833 JST [7327] LOG: parameter "synchronous_standby_names" changed to "*"
+ DEST_NODE_HOST=t1117psgl
+ DEST_NODE_PGDATA=/var/lib/pgsql/data
+ POSTGRESQL_STARTUP_USER=postgres
+ SSH_KEY_FILE=id_rsa
+ SSH_OPTIONS='-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i ~/.ssh/id_rsa'
+ SSH_CMD='ssh -T -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i ~/.ssh/id_rsa postgres@t1117psgl'
+ ssh -T -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i '~/.ssh/id_rsa' postgres@t1117psgl '/usr/bin/pg_ctl start -D /var/lib/pgsql/data -w -l /dev/null'
Warning: Permanently added 't1117psgl,192.168.11.117' (ECDSA) to the list of known hosts.
waiting for server to start.... done
server started
+ exit 0
2023-08-27 11:23:19.606 JST [19019] LOG: standby "t1117psgl" is now a synchronous standby with priority 1
2023-08-27 11:23:19.606 JST [19019] STATEMENT: START_REPLICATION 0/6000000 TIMELINE 2
</code></pre>
<p>Pgpool-IIのログ(<code>/var/log/pgpool_log/pgpool-*.log</code>)に以下の通り出力される。</p>
<pre><code>2023-08-27 11:23:17.984: pcp_child pid 9523: LOG: starting recovering node 0
2023-08-27 11:23:17.996: pcp_child pid 9523: LOG: executing recovery
2023-08-27 11:23:17.996: pcp_child pid 9523: DETAIL: starting recovery command: "SELECT pgpool_recovery('replication_mode_recovery_1st_stage', 't1117psgl', '/var/lib/pgsql/data', '5432', 0, '5432', 't1118psgl')"
2023-08-27 11:23:17.996: pcp_child pid 9523: LOG: executing recovery
2023-08-27 11:23:17.996: pcp_child pid 9523: DETAIL: disabling statement_timeout
2023-08-27 11:23:18.834: pcp_child pid 9523: LOG: node recovery, 1st stage is done
2023-08-27 11:23:19.411: pcp_child pid 9523: LOG: checking if postmaster is started
2023-08-27 11:23:19.411: pcp_child pid 9523: DETAIL: trying to connect to postmaster on hostname:t1117psgl database:postgres user:postgres (retry 0 times)
2023-08-27 11:23:19.422: pcp_child pid 9523: LOG: node recovery, node: 0 restarted
2023-08-27 11:23:19.422: pcp_child pid 9523: LOG: received failback request for node_id: 0 from pid [9523]
2023-08-27 11:23:19.422: pcp_child pid 9523: LOG: signal_user1_to_parent_with_reason(0)
2023-08-27 11:23:19.422: main pid 8071: LOG: Pgpool-II parent process received SIGUSR1
2023-08-27 11:23:19.422: main pid 8071: LOG: Pgpool-II parent process has received failover request
2023-08-27 11:23:19.422: main pid 8071: LOG: === Starting fail back. reconnect host t1117psgl(5432) ===
2023-08-27 11:23:19.422: main pid 8071: LOG: Node 1 is not down (status: 2)
2023-08-27 11:23:19.422: main pid 8071: LOG: Do not restart children because we are failing back node id 0 host: t1117psgl port: 5432 and we are in streaming replication mode and not all backends were down
2023-08-27 11:23:19.422: main pid 8071: LOG: find_primary_node_repeatedly: waiting for finding a primary node
2023-08-27 11:23:19.435: main pid 8071: LOG: find_primary_node: standby node is 0
2023-08-27 11:23:19.435: main pid 8071: LOG: find_primary_node: primary node is 1
2023-08-27 11:23:19.435: main pid 8071: LOG: failover: set new primary node: 1
2023-08-27 11:23:19.435: main pid 8071: LOG: failover: set new main node: 0
2023-08-27 11:23:19.435: main pid 8071: LOG: === Failback done. reconnect host t1117psgl(5432) ===
2023-08-27 11:23:19.435: sr_check_worker pid 9518: LOG: worker process received restart request
2023-08-27 11:23:19.436: pcp_child pid 9523: LOG: recovery done
</code></pre>
<h3 id="事後状態確認-1">3. 事後状態確認</h3>
<p>オンラインリカバリ後の状態確認を行う。node_id: 0がstandbyかつステータスがupになっており、復旧していることが確認できる。</p>
<pre><code>[Pgpool]$ psql -p 9999 -x -c "show pool_nodes"
-[ RECORD 1 ]----------+--------------------
node_id | 0
hostname | t1117psgl
port | 5432
status | up ←★upに変化している
pg_status | up ←★upに変化している
lb_weight | 0.500000
role | standby
pg_role | standby ←★standbyに変化している
select_cnt | 0
load_balance_node | true
replication_delay | 0
replication_state | streaming ←★streamingとなっている
replication_sync_state | sync ←★syncステータスとなっている
last_status_change | 2023-08-27 11:23:29
-[ RECORD 2 ]----------+--------------------
node_id | 1
hostname | t1118psgl
port | 5432
status | up
pg_status | up
lb_weight | 0.500000
role | primary
pg_role | primary
select_cnt | 0
load_balance_node | false
replication_delay | 0
replication_state |
replication_sync_state |
last_status_change | 2023-08-27 11:21:31
</code></pre>
<p>以上で、Pgpool-IIを使ってフェイルオーバーとオンラインリカバリを実行するための手順は完了となる。</p>
tech-mmmmhttp://www.blogger.com/profile/01739191108051432575noreply@blogger.com0