技術分享 | MySQL 如何適配 AppArmor

愛可生雲資料庫發表於2021-12-15

作者:楊濤濤

資深資料庫專家,專研 MySQL 十餘年。擅長 MySQL、PostgreSQL、MongoDB 等開源資料庫相關的備份恢復、SQL 調優、監控運維、高可用架構設計等。目前任職於愛可生,為各大運營商及銀行金融企業提供 MySQL 相關技術支援、MySQL 相關課程培訓等工作。

本文來源:原創投稿

*愛可生開源社群出品,原創內容未經授權不得隨意使用,轉載請聯絡小編並註明來源。


引言

AppArmor (Debian 系平臺)是一款核心級別的安全機制,通過 AppArmor 來讓 Linux 系統實現嚴格的資源訪問控制,類似 SELinux(RedHat 系列平臺)。

我本地環境為:OS 版本 Ubuntu 18,DB 版本 MySQL 8.0.27。

AppArmor 通過目錄/etc/apparmor.d/ 下的一系列配置檔案來分別限制每個程式對 OS 資源的訪問許可權。

AppArmor 有兩種工作模式:

  1. Enforced/Confined: 嚴格按照配置檔案來限制對應的程式訪問OS資源的行為,拒絕不在配置範圍內的程式執行。
  2. Complaining/Learning: 僅記錄程式行為,不對其進行限制。

遇到的問題是:

我啟動 MySQL ,未成功:

root@ytt-ubuntu:~# systemctl start mysql
Job for mysql.service failed because the control process exited with error code.
See "systemctl status mysql.service" and "journalctl -xe" for details.

我摘出來幾條核心的錯誤資訊:

root@ytt-ubuntu:~# journalctl -xe
-- Defined-By: systemd

-- user-122.slice 單元已結束停止操作。
11月 16 16:14:00 ytt-ubuntu kernel: audit: type=1400 audit(1637050440.395:101): apparmor="DENIED" operation="mknod" profile="/usr/sbin/mysqld" name="/op
11月 16 16:14:00 ytt-ubuntu audit[7237]: AVC apparmor="DENIED" operation="mknod" profile="/usr/sbin/mysqld" name="/opt/mysql/data/mysqld_tmp_file_case_i
11月 16 16:14:01 ytt-ubuntu audit[7270]: AVC apparmor="DENIED" operation="mknod" profile="/usr/sbin/mysqld" name="/opt/mysql/log/error.log" pid=7270 com
11月 16 16:14:01 ytt-ubuntu systemd[1]: mysql.service: Main process exited, code=exited, status=1/FAILURE
11月 16 16:14:01 ytt-ubuntu systemd[1]: mysql.service: Failed with result 'exit-code'.
11月 16 16:14:01 ytt-ubuntu systemd[1]: Failed to start MySQL Community Server.
-- Subject: mysql.service 單元已失敗

由錯誤資訊可以看到,AppArmor 阻止了 MySQL 服務啟動,可能的原因是啟動 MySQL 服務需要訪問的目錄在 AppArmor 裡沒有配置。

想起來我動過配置檔案:

源配置內容:
[mysqld]
pid-file       = /var/run/mysqld/mysqld.pid
socket         = /var/run/mysqld/mysqld.sock 
datadir        = /var/lib/mysql
log-error      = /var/log/mysql/error.log
我改後的配置內容:
[mysqld]           
pid-file        = /opt/mysql/mysqld.pid
socket          = /opt/mysql/mysqld.sock
datadir         = /opt/mysql/data
log-error       = /opt/mysql/log/error.log

此時有兩種方法來解決這個問題。

第一, 直接更改AppArmor 的配置檔案:

給/etc/apparmor.d/user.sbin.mysqld裡新增如下內容:(或者把原來MySQL相關的目錄替換掉也行)


# pid,socket等檔案目錄

  /opt/mysql/* rw,

# 資料目錄內容 

 /opt/mysql/data/ r,
 /opt/mysql/data/** rwk,

#日誌檔案內容

 /opt/mysql/log/ r,
 /opt/mysql/log** rw,

過載 AppArmor 服務

root@ytt-ubuntu:~# systemctl reload apparmor

再次重啟 MySQL ,啟動成功。

root@ytt-ubuntu:/opt/mysql# systemctl start mysql

檢視狀態

root@ytt-ubuntu:/home/ytt# systemctl status mysql
● mysql.service - MySQL Community Server
   Loaded: loaded (/lib/systemd/system/mysql.service; disabled; vendor preset: enabled)
   Active: activating (start) since Tue 2021-11-16 16:49:12 CST; 40s ago
     Docs: man:mysqld(8)
           http://dev.mysql.com/doc/refman/en/using-systemd.html
  Process: 3137 ExecStartPre=/usr/share/mysql-8.0/mysql-systemd-start pre (code=exited, status=0/SUCCESS)
 Main PID: 3191 (mysqld)
   Status: "Server startup in progress"
    Tasks: 24 (limit: 4915)
   CGroup: /system.slice/mysql.service
           └─3191 /usr/sbin/mysqld

11月 16 16:49:12 ytt-ubuntu systemd[1]: Starting MySQL Community Server...
11月 16 16:49:54 ytt-ubuntu systemd[1]: Started MySQL Community Server.
第二, 改變 AppArmor 的預設工作模式,由強制模式改為抱怨模式:

得先安裝 apparmor-utils 包,裡面包含了很多有用的程式來操作 AppArmor .

root@ytt-ubuntu:~# apt-get install apparmor-utils

單獨配置 MySQL 服務進入抱怨模式:

root@ytt-ubuntu:~# aa-complain /etc/apparmor.d/usr.sbin.mysqld 
Setting /etc/apparmor.d/usr.sbin.mysqld to complain mode.

過載 AppArmor

root@ytt-ubuntu:~# systemctl reload apparmor

啟動 MySQL 服務

root@ytt-ubuntu:~# systemctl restart mysql

檢視狀態

root@ytt-ubuntu:~# systemctl status mysql
● mysql.service - MySQL Community Server
   Loaded: loaded (/lib/systemd/system/mysql.service; disabled; vendor preset: enabled)
   Active: active (running) since Tue 2021-11-16 17:11:12 CST; 12s ago
     Docs: man:mysqld(8)
           http://dev.mysql.com/doc/refman/en/using-systemd.html
  Process: 3712 ExecStartPre=/usr/share/mysql-8.0/mysql-systemd-start pre (code=exited, status=0/SUCCESS)
 Main PID: 3767 (mysqld)
   Status: "Server is operational"
    Tasks: 41 (limit: 4915)
   CGroup: /system.slice/mysql.service
           └─3767 /usr/sbin/mysqld

11月 16 17:10:45 ytt-ubuntu systemd[1]: Starting MySQL Community Server...
11月 16 17:11:12 ytt-ubuntu systemd[1]: Started MySQL Community Server.
以上MySQL的行為基 zat於APT包安裝產生,如果採用MySQL二進位制包安裝,則可以規避這個問題。

相關文章