C10-OpenStack 基礎服務與高可用配置 (下)

0. 環境與準備

0.1 本課環境

主機角色管理網 IP
jmp001學員操作機(OpenStack CLI)10.127.0.3
ctl001控制節點10.127.0.4
ctl002控制節點10.127.0.14
ctl003控制節點10.127.0.15
—VIP10.127.0.250

資料庫的連線路徑:

OpenStack 服務(nova、neutron、keystone …)
        │  mysql://<服務帳號>@10.127.0.250:3306
        ▼
ProxySQL(每台控制節點都有一個,VIP 在哪台就由哪台的 ProxySQL 接手)
        │  依 hostgroup 規則選擇後端
        ▼
MariaDB-Galera 三節點叢集(ctl001 / ctl002 / ctl003,同步複寫)

0.2 連線方式

全班與講師共用 jmp001 與控制節點上的 ubuntu 帳號(具 sudo 權限)。先登入 jmp001,再從 jmp001 SSH 到控制節點:

指令
ssh ubuntu@10.127.0.4

指令標示:[jmp001] 在 jmp001 執行;[ctl] 在任一台控制節點執行;[ctl003] 在指定節點執行。

⚠️ 規則

  • 你使用的是和講師相同的管理員權限
  • 預期輸出是示意,數字、時間、順序可能與你看到的不同

0.3 登入資料庫的方式

Part A、Part B 都是先登入,再直接輸入 SQL。登入指令會自己從控制節點上的設定檔讀出密碼,不需要另外查。

MariaDB(Part A),以 root 登入:

指令
# [ctl]
sudo docker exec -it mariadb mysql -uroot -p$(sudo grep sst_auth /etc/kolla/mariadb/galera.cnf | cut -d: -f2)

ProxySQL 管理介面(Part B),以 kolla-admin 登入:

指令
# [ctl]
sudo docker exec -it mariadb mysql -h 10.127.0.250 -P 6032 -u kolla-admin -p$(sudo grep admin_credentials /etc/kolla/proxysql/proxysql.yaml | cut -d: -f3 | tr -d '"')
帳號密碼從哪裡讀指令中的處理
root/etc/kolla/mariadb/galera.cnf 的 wsrep_sst_auth = root:<密碼>(Galera 完整同步時用 root 登入,所以 kolla 把密碼放在這裡)cut -d: -f2 取冒號後面的部分
kolla-admin/etc/kolla/proxysql/proxysql.yaml 的 admin_credentials: "kolla-admin:<密碼>"cut -d: -f3 取第二個冒號後面的部分,tr -d '"' 去掉結尾的引號

Part A:MariaDB-Galera

Galera 是同步多主(multi-master)複寫:每一筆交易在 commit 時,會送到叢集所有節點完成認證,所以三台的資料隨時一致。

A0. 服務怎麼連到資料庫?

指令
# [ctl]
sudo grep 'connection =' /etc/kolla/nova-api/nova.conf | cut -d@ -f2

預期輸出:

預期輸出
10.127.0.250:3306/nova_cell0
10.127.0.250:3306/nova_api

cut -d@ -f2 只留下 @ 後面的部分,把連線字串前段的帳號與密碼去掉。

A1. Galera 的連接埠與設定

指令
# [ctl]
sudo ss -lntp | grep mariadbd
sudo grep wsrep_cluster /etc/kolla/mariadb/galera.cnf

預期輸出(以 ctl001 為例):

預期輸出
LISTEN 0  900   10.127.0.4:3306  0.0.0.0:*  users:(("mariadbd",pid=27082,fd=38))
LISTEN 0  4096  10.127.0.4:4567  0.0.0.0:*  users:(("mariadbd",pid=27082,fd=8))
wsrep_cluster_address = gcomm://10.127.0.4:4567,10.127.0.14:4567,10.127.0.15:4567
wsrep_cluster_name = openstack
Port用途現在有沒有在聽
3306SQL 連線有
4567Galera 節點之間的複寫通訊(wsrep)有
4568IST(增量同步:節點短暫離線後只補缺少的交易)沒有,只在同步時才開
4444SST(完整同步:用 mariabackup 複製整個資料庫)沒有,只在同步時才開

wsrep_cluster_address 列出三台的 4567:節點啟動時就是照這份名單找到其他成員。設定檔就是投影片提到的 /etc/kolla/mariadb/galera.cnf。

A2. 登入 MariaDB:資料庫與 wsrep 健康指標

登入 MariaDB:

指令
# [ctl]
sudo docker exec -it mariadb mysql -uroot -p$(sudo grep sst_auth /etc/kolla/mariadb/galera.cnf | cut -d: -f2)

先看有哪些資料庫:

指令
SHOW DATABASES;

預期輸出:

預期輸出
+---------------------+
| Database            |
+---------------------+
| cinder              |
| glance              |
| heat                |
| information_schema  |
| keystone            |
| mysql               |
| neutron             |
| nova                |
| nova_api            |
| nova_cell0          |
| octavia             |
| octavia_persistence |
| performance_schema  |
| placement           |
| sys                 |
+---------------------+

對照投影片「各服務的資料庫」:keystone、nova / nova_api、placement、neutron、glance、cinder 都在這裡;information_schema、mysql、performance_schema、sys 是 MariaDB 自己的系統資料庫。

接著逐條輸入 wsrep 狀態變數:

指令
SHOW STATUS LIKE 'wsrep_cluster_size';
SHOW STATUS LIKE 'wsrep_cluster_status';
SHOW STATUS LIKE 'wsrep_ready';
SHOW STATUS LIKE 'wsrep_local_state_comment';
SHOW STATUS LIKE 'wsrep_flow_control_paused';
SHOW STATUS LIKE 'wsrep_local_recv_queue';

預期輸出:

預期輸出
+--------------------+-------+
| Variable_name      | Value |
+--------------------+-------+
| wsrep_cluster_size | 3     |
+--------------------+-------+
+----------------------+---------+
| Variable_name        | Value   |
+----------------------+---------+
| wsrep_cluster_status | Primary |
+----------------------+---------+
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| wsrep_ready   | ON    |
+---------------+-------+
+---------------------------+--------+
| Variable_name             | Value  |
+---------------------------+--------+
| wsrep_local_state_comment | Synced |
+---------------------------+--------+
+---------------------------+------------+
| Variable_name             | Value      |
+---------------------------+------------+
| wsrep_flow_control_paused | 0.00358723 |
+---------------------------+------------+
+------------------------+-------+
| Variable_name          | Value |
+------------------------+-------+
| wsrep_local_recv_queue | 0     |
+------------------------+-------+
判斷狀態變數健康值異常代表
叢集是否可用wsrep_cluster_size3小於 3 代表有節點離線
wsrep_cluster_statusPrimarynon-Primary 代表失去 quorum
wsrep_readyONOFF 代表節點不接受查詢
叢集是否健康wsrep_local_state_commentSyncedJoining / Donor 代表正在同步
wsrep_flow_control_paused接近 0偏高代表某節點複製落後,拖慢整體寫入
wsrep_local_recv_queue接近 0持續增加代表節點套用交易跟不上

日常巡檢至少確認 cluster_size = 3、status = Primary、ready = ON。做完輸入 exit 離開 MariaDB。

Quorum(p.07):3 節點的 Galera 需要過半數(2 台)存活。1 台故障仍是 Primary;2 台故障時剩下的節點變成 non-Primary 並拒絕查詢(wsrep_ready = OFF),避免網路分割時兩側各自寫入。

A3. 三台一次檢查:clustercheck

clustercheck 是 MariaDB container 內建的健康檢查,docker ps 看到的 (healthy) 就是它的結果。從 jmp001 一次檢查三台:

指令
# [jmp001]
for i in 4 14 15; do ssh 10.127.0.$i "hostname; sudo docker exec mariadb clustercheck"; done

預期輸出:

預期輸出
ctl001-6161060-iaas
HTTP/1.1 200 OK
Content-Type: text/plain
Connection: close
Content-Length: 32

Galera cluster node is synced.
ctl002-6161063-iaas
HTTP/1.1 200 OK
...
Galera cluster node is synced.
ctl003-6161069-iaas
HTTP/1.1 200 OK
...
Galera cluster node is synced.

A4. 從日誌看節點加入叢集

指令
# [ctl]
sudo grep Synchronized /var/log/kolla/mariadb/mariadb.log | tail -3

預期輸出(以 ctl001 為例):

預期輸出
2026-10-17 11:47:48 8 [Note] WSREP: Synchronized with group, ready for connections
2026-10-17 11:48:12 2 [Note] WSREP: Synchronized with group, ready for connections
2026-10-17 11:48:29 2 [Note] WSREP: Synchronized with group, ready for connections

每一行代表這個節點完成同步、開始接受連線,通常出現在部署或重啟之後。最後一行的時間就是這個節點最近一次加入叢集的時間。


Part B:ProxySQL

B1. ProxySQL 聽在哪裡?

指令
# [ctl]
sudo ss -lntp | grep proxysql
sysctl net.ipv4.ip_nonlocal_bind

預期輸出(以 ctl003 為例):

預期輸出
LISTEN 0  128   10.127.0.250:6032  0.0.0.0:*  users:(("proxysql",pid=23819,fd=45))
LISTEN 0  128   10.127.0.15:6032   0.0.0.0:*  users:(("proxysql",pid=23819,fd=44))
LISTEN 0  1024  10.127.0.250:3306  0.0.0.0:*  users:(("proxysql",pid=23819,fd=43))
LISTEN 0  1024  10.127.0.250:3306  0.0.0.0:*  users:(("proxysql",pid=23819,fd=42))
...
net.ipv4.ip_nonlocal_bind = 1
監聽位址用途
10.127.0.250:3306OpenStack 服務連的資料庫入口(VIP);有多行是因為 ProxySQL 開了多個執行緒同時接收
:6032ProxySQL 管理介面

和 A1 比較:MariaDB 聽在本機 IP 的 3306,ProxySQL 聽在 VIP 的 3306,兩者不衝突。

三台控制節點都會看到 10.127.0.250:3306,即使 VIP 不在這台。這是因為 ip_nonlocal_bind = 1 允許程式綁定「還不在本機」的 IP:每台的 ProxySQL 都先聽好 VIP,VIP 漂到哪一台,那台就立刻接手。

B2. 設定檔:權重 100 / 10 / 10

投影片提到的設定檔 /etc/kolla/proxysql/proxysql.yaml,最後 32 行是後端與 hostgroup 的設定:

指令
# [ctl]
sudo tail -n 32 /etc/kolla/proxysql/proxysql.yaml

預期輸出:

預期輸出
mysql_servers:
  - address: "10.127.0.4"
    port :  3306
    hostgroup :  0
    max_connections: 10000
    max_replication_lag: 0
    weight :  100
    comment :  "Writer ctl001"
  - address: "10.127.0.14"
    port :  3306
    hostgroup :  0
    max_connections: 10000
    max_replication_lag: 0
    weight :  10
    comment :  "Writer ctl002"
  - address: "10.127.0.15"
    port :  3306
    hostgroup :  0
    max_connections: 10000
    max_replication_lag: 0
    weight :  10
    comment :  "Writer ctl003"

mysql_galera_hostgroups:
  - writer_hostgroup: 0
    backup_writer_hostgroup: 1
    reader_hostgroup: 2
    offline_hostgroup: 3
    max_connections: 10000
    max_writers: 1
    writer_is_also_reader: 0
    comment: "Galera cluster for shard 0"

B3. 執行中的狀態:只有一個寫入節點

設定檔是 ProxySQL 啟動時讀的內容;實際運作的狀態要登入管理介面看:

指令
# [ctl]
sudo docker exec -it mariadb mysql -h 10.127.0.250 -P 6032 -u kolla-admin -p$(sudo grep admin_credentials /etc/kolla/proxysql/proxysql.yaml | cut -d: -f3 | tr -d '"')

-h 10.127.0.250 連的是 VIP,也就是目前正在處理流量的那一台 ProxySQL。登入後輸入:

指令
SELECT hostgroup_id, hostname, status, weight, comment FROM runtime_mysql_servers;
SELECT * FROM runtime_mysql_galera_hostgroups\G

預期輸出:

預期輸出
+--------------+-------------+---------+--------+---------------+
| hostgroup_id | hostname    | status  | weight | comment       |
+--------------+-------------+---------+--------+---------------+
| 0            | 10.127.0.14 | SHUNNED | 10     | Writer ctl002 |
| 0            | 10.127.0.15 | SHUNNED | 10     | Writer ctl003 |
| 0            | 10.127.0.4  | ONLINE  | 100    | Writer ctl001 |
| 1            | 10.127.0.14 | ONLINE  | 10     | Writer ctl002 |
| 1            | 10.127.0.15 | ONLINE  | 10     | Writer ctl003 |
+--------------+-------------+---------+--------+---------------+
*************************** 1. row ***************************
       writer_hostgroup: 0
backup_writer_hostgroup: 1
       reader_hostgroup: 2
      offline_hostgroup: 3
                 active: 1
            max_writers: 1
  writer_is_also_reader: 0
max_transactions_behind: 0
                comment: Galera cluster for shard 0
hostgroup角色成員
0writer:實際接收讀寫的節點只有 ctl001 是 ONLINE(weight 最高);另外兩台是 SHUNNED(暫不使用)
1backup writer:writer 故障時遞補ctl002、ctl003
2reader空的(writer_is_also_reader = 0)
3offline:健康檢查失敗的節點目前沒有

Galera 雖然每台都能寫入,但多台同時寫入同一筆資料時,會在 commit 時發生認證衝突,對 OpenStack 服務來說就是間歇性的 deadlock 錯誤。所以 kolla 用 max_writers = 1 讓所有讀寫集中在一台,另外兩台是熱備援。

保持登入,繼續 B4。

B4. 連線管理與健康監控

在同一個 ProxySQL 管理介面裡輸入:

指令
SELECT hostgroup, srv_host, status, ConnUsed, ConnFree, ConnOK, ConnERR, Queries FROM stats_mysql_connection_pool;

預期輸出:

預期輸出
+-----------+-------------+---------+----------+----------+--------+---------+---------+
| hostgroup | srv_host    | status  | ConnUsed | ConnFree | ConnOK | ConnERR | Queries |
+-----------+-------------+---------+----------+----------+--------+---------+---------+
| 0         | 10.127.0.15 | SHUNNED | 0        | 0        | 0      | 0       | 0       |
| 0         | 10.127.0.14 | SHUNNED | 0        | 0        | 0      | 0       | 0       |
| 0         | 10.127.0.4  | ONLINE  | 0        | 105      | 115    | 0       | 7358151 |
| 1         | 10.127.0.14 | ONLINE  | 0        | 0        | 0      | 0       | 0       |
| 1         | 10.127.0.15 | ONLINE  | 0        | 0        | 0      | 0       | 0       |
+-----------+-------------+---------+----------+----------+--------+---------+---------+
欄位意義
ConnUsed / ConnFree正在使用 / 閒置在連線池中的後端連線
ConnOK / ConnERR成功 / 失敗建立的後端連線數
Queries送到這個後端的查詢總數

所有查詢都送到 ctl001,而且 ProxySQL 只用了約 100 條後端連線,就承接了所有 OpenStack 服務的資料庫請求:這就是投影片說的連線管理。

再看 ProxySQL 的健康監控紀錄:

指令
SELECT hostname, primary_partition, read_only, wsrep_local_state, error FROM monitor.mysql_server_galera_log ORDER BY time_start_us DESC LIMIT 3;

預期輸出:

預期輸出
+-------------+-------------------+-----------+-------------------+-------+
| hostname    | primary_partition | read_only | wsrep_local_state | error |
+-------------+-------------------+-----------+-------------------+-------+
| 10.127.0.4  | YES               | NO        | 4                 | NULL  |
| 10.127.0.15 | YES               | NO        | 4                 | NULL  |
| 10.127.0.14 | YES               | NO        | 4                 | NULL  |
+-------------+-------------------+-----------+-------------------+-------+

做完輸入 exit 離開。


Part C:Keystone

C0. 準備

指令
# [jmp001]
export NN=01                                     # ← 換成你的學員編號(01–20)
source ~/venv/bin/activate
source ~/creds/stu${NN}-openrc.sh    # 你的管理員身分(admin project 的 admin)
openstack token issue -c expires -c project_id -c user_id

預期輸出:

預期輸出
+------------+----------------------------------+
| Field      | Value                            |
+------------+----------------------------------+
| expires    | 2026-10-28T10:12:57+0000         |
| project_id | b090dcce347d41c6bf311869209e5364 |
| user_id    | 947465eda0184458963bafb884996f01 |
+------------+----------------------------------+

C1. Keystone 的容器與 Fernet keys

指令
# [ctl]
sudo docker ps --filter name=keystone
sudo grep provider /etc/kolla/keystone/keystone.conf

預期輸出:

預期輸出
CONTAINER ID   IMAGE                                                         ...   STATUS                 NAMES
e28ae35cde09   quay.io/openstack.kolla/keystone:2025.1-ubuntu-noble          ...   Up 10 days (healthy)   keystone
846768e3ff92   quay.io/openstack.kolla/keystone-fernet:2025.1-ubuntu-noble   ...   Up 10 days (healthy)   keystone_fernet
dbb6cd6ae04c   quay.io/openstack.kolla/keystone-ssh:2025.1-ubuntu-noble      ...   Up 10 days (healthy)   keystone_ssh
provider = fernet
容器用途
keystoneIdentity API,簽發與驗證 token
keystone_fernet定期輪替 Fernet keys(用來簽發 token)
keystone_ssh在三台控制節點之間同步 Fernet keys

provider = fernet:token 用 Fernet keys 加密簽發。三台的 keys 必須一致,否則某台簽的 token 到另一台會驗證失敗。比對三台的 keys:

指令
# [jmp001]
for i in 4 14 15; do ssh 10.127.0.$i "hostname; sudo docker exec keystone_fernet sh -c 'md5sum /etc/keystone/fernet-keys/*'"; done

預期輸出(雜湊值只列前 8 碼):

預期輸出
ctl001-6161060-iaas
3779fb7e...  /etc/keystone/fernet-keys/0
c752062e...  /etc/keystone/fernet-keys/3
64b730e6...  /etc/keystone/fernet-keys/4
ctl002-6161063-iaas
3779fb7e...  /etc/keystone/fernet-keys/0
c752062e...  /etc/keystone/fernet-keys/3
64b730e6...  /etc/keystone/fernet-keys/4
ctl003-6161069-iaas
3779fb7e...  /etc/keystone/fernet-keys/0
c752062e...  /etc/keystone/fernet-keys/3
64b730e6...  /etc/keystone/fernet-keys/4

三台的檔名與雜湊值完全相同,代表 keys 一致。如果不一致,症狀是間歇性 401:token 只在部分節點驗證成功。

各服務 API 會快取 token 的驗證結果,看看 Nova 把快取放在哪裡:

指令
# [ctl]
sudo grep memcached_servers /etc/kolla/nova-api/nova.conf

預期輸出:

預期輸出
memcached_servers = 10.127.0.4:11211,10.127.0.14:11211,10.127.0.15:11211

本環境的 keystonemiddleware 把驗證結果放在三台的 memcached(投影片寫的預設是 in-process 快取,memcached 為選用)。快取有效期間內,Keystone 短暫異常也不會讓既有的 token 立刻失效。

C2. Service Catalog 與 Endpoint

指令
# [jmp001]
openstack catalog list -c Name -c Type
openstack endpoint list --service identity

預期輸出:

預期輸出
+-----------+----------------+
| Name      | Type           |
+-----------+----------------+
| glance    | image          |
| octavia   | load-balancer  |
| heat-cfn  | cloudformation |
| nova      | compute        |
| placement | placement      |
| cinder    | block-storage  |
| cinderv3  | volumev3       |
| neutron   | network        |
| heat      | orchestration  |
| keystone  | identity       |
+-----------+----------------+
+----------------------------------+-----------+--------------+--------------+---------+-----------+--------------------------+
| ID                               | Region    | Service Name | Service Type | Enabled | Interface | URL                      |
+----------------------------------+-----------+--------------+--------------+---------+-----------+--------------------------+
| 11783862106c4a408b8db6f955f7f784 | RegionOne | keystone     | identity     | True    | internal  | http://10.127.0.250:5000 |
| 23f875bd0bb245e09bf70de192d669d7 | RegionOne | keystone     | identity     | True    | public    | http://10.127.0.250:5000 |
+----------------------------------+-----------+--------------+--------------+---------+-----------+--------------------------+

一個 endpoint = Service type + Region + Interface + URL:

Interface給誰使用本環境
public外部使用者或公開網路有,指向 VIP
internal服務之間或內部網路呼叫有,指向 VIP(CLI 設定 OS_INTERFACE=internal)
admin管理者或控制平面使用沒有建立(C5 會用到這一點)

C3. 建立 project、user、group 與角色指派

指令
# [jmp001]
openstack project create --domain Default --description "C10 lab stu${NN}" c10-stu${NN} -c name -c id
openstack user create --domain Default --project c10-stu${NN} --password "C10-Lab-${NN}" c10-stu${NN}-user -c name -c id
openstack group create --domain Default c10-stu${NN}-grp -c name -c id
openstack group add user c10-stu${NN}-grp c10-stu${NN}-user
openstack role add --project c10-stu${NN} --group c10-stu${NN}-grp member

預期輸出:

預期輸出
+-------+----------------------------------+
| Field | Value                            |
+-------+----------------------------------+
| id    | 677512d7cc3741ac8b417ad4129d407e |
| name  | c10-stu01                        |
+-------+----------------------------------+
+-------+----------------------------------+
| Field | Value                            |
+-------+----------------------------------+
| id    | ebcae47b02f6455e8054ff2f26a8451a |
| name  | c10-stu01-user                   |
+-------+----------------------------------+
+-------+----------------------------------+
| Field | Value                            |
+-------+----------------------------------+
| id    | 7a6b5c4d3e2f41a0b9c8d7e6f5a4b3c2 |
| name  | c10-stu01-grp                    |
+-------+----------------------------------+

角色是指派給 group,不是直接給 user。看看 Keystone 記錄了什麼:

指令
# [jmp001]
openstack role assignment list --project c10-stu${NN} --names
openstack role assignment list --project c10-stu${NN} --names --effective

預期輸出:

預期輸出
+--------+------+-----------------------+-------------------+--------+--------+-----------+
| Role   | User | Group                 | Project           | Domain | System | Inherited |
+--------+------+-----------------------+-------------------+--------+--------+-----------+
| member |      | c10-stu01-grp@Default | c10-stu01@Default |        |        | False     |
+--------+------+-----------------------+-------------------+--------+--------+-----------+
+--------+------------------------+-------+-------------------+--------+--------+-----------+
| Role   | User                   | Group | Project           | Domain | System | Inherited |
+--------+------------------------+-------+-------------------+--------+--------+-----------+
| member | c10-stu01-user@Default |       | c10-stu01@Default |        |        | False     |
| reader | c10-stu01-user@Default |       | c10-stu01@Default |        |        | False     |
+--------+------------------------+-------+-------------------+--------+--------+-----------+
觀察說明
第一個表實際存在的 role assignment:group + member + project
--effective展開後,user 經由 group 取得 member;member 又隱含 reader
--project 建 user只是設定預設 project,不給任何權限

角色的隱含關係(admin → manager → member → reader):

指令
# [jmp001]
openstack implied role list -c "Prior Role Name" -c "Implied Role Name"

預期輸出:

預期輸出
+-----------------+-------------------+
| Prior Role Name | Implied Role Name |
+-----------------+-------------------+
| manager         | member            |
| member          | reader            |
| admin           | manager           |
+-----------------+-------------------+

C4. 切換成新使用者

開一個子 shell,只把帳號、密碼、project 換成新使用者,其他設定(auth URL、domain、interface)沿用原本的:

指令
# [jmp001]
bash
export OS_USERNAME=c10-stu${NN}-user OS_PASSWORD=C10-Lab-${NN} OS_PROJECT_NAME=c10-stu${NN}
openstack token issue -c expires -c project_id -c user_id

預期輸出:

預期輸出
+------------+----------------------------------+
| Field      | Value                            |
+------------+----------------------------------+
| expires    | 2026-10-28T10:13:11+0000         |
| project_id | 677512d7cc3741ac8b417ad4129d407e |
| user_id    | ebcae47b02f6455e8054ff2f26a8451a |
+------------+----------------------------------+

C5 在這個子 shell 裡繼續。

C5. 三種常見錯誤的診斷

每一組刻意製造一種錯誤,觀察錯誤碼,再對照投影片的診斷順序。指令前面的 變數=值 只對這一行有效。

① 401:無法取得 token(認證問題)

指令
OS_PASSWORD=wrong-password openstack token issue
OS_USER_DOMAIN_NAME=heat_user_domain openstack token issue
OS_PROJECT_NAME=admin openstack token issue

預期輸出:

預期輸出
The request you have made requires authentication. (HTTP 401) (Request-ID: req-7b9e38c7-...)
The request you have made requires authentication. (HTTP 401) (Request-ID: req-1dfd82db-...)
The request you have made requires authentication. (HTTP 401) (Request-ID: req-d9961439-...)
指令原因
密碼錯憑證無效
user domain 指錯heat_user_domain 裡沒有這個 user
範圍指向 admin project帳密正確,但 user 在 admin project 沒有任何角色,Keystone 不發這個範圍的 token

② 403:拿得到 token,但 API 被拒絕(授權問題)

指令
openstack network create c10-stu${NN}-net -c name -c project_id
openstack user list
openstack server list --all-projects
openstack network show demo-net

預期輸出:

預期輸出
+------------+----------------------------------+
| Field      | Value                            |
+------------+----------------------------------+
| name       | c10-stu01-net                    |
| project_id | 677512d7cc3741ac8b417ad4129d407e |
+------------+----------------------------------+
ForbiddenException: 403: Client Error for url: http://10.127.0.250:5000/v3/users, You are not authorized to perform the requested action: identity:list_users.
ForbiddenException: 403: Client Error for url: http://10.127.0.250:8774/v2.1/servers/detail?deleted=False&all_tenants=True, Policy doesn't allow os_compute_api:servers:detail:get_all_tenants to be performed.
Error while executing command: No Network found for demo-net
指令結果說明
在自己的 project 建網路成功member 在自己的 project 可以建立資源
user list403Keystone 的 policy:列出 user 需要 admin 或 domain / system 範圍的角色
server list --all-projects403Nova 的 policy:只有 admin 能看所有 project 的 VM
network show demo-net找不到Neutron 直接把別人的網路藏起來,連「存在」都看不到

錯誤訊息裡的 identity:list_users、os_compute_api:servers:detail:get_all_tenants 就是被拒絕的 policy 規則名稱。

③ Endpoint not found:找不到服務(catalog 問題)

指令
OS_REGION_NAME=RegionTwo openstack server list
OS_INTERFACE=admin openstack server list

預期輸出:

預期輸出
internal endpoint for compute service in RegionTwo region not found
admin endpoint for compute service not found

token 是有效的,帳密和角色也都沒問題,只是 catalog 裡找不到符合「service type + region + interface」的 endpoint。

診斷順序(p.21)

現象優先檢查本節的例子
401 Unauthorizedauth URL、帳密、user domain、scope 的 project 是否有角色①
403 Forbiddentoken scope、role assignment、目標服務 policy②
Endpoint not foundopenstack catalog list、region、interface、service type③
無法管理 user / projectdomain scope 與 Keystone policy② 的 user list

做完離開子 shell,回到管理員身分:

指令
exit
echo $OS_USERNAME

預期輸出:

預期輸出
stu01

C6. 角色不等於權限

建立一個自訂角色,並且只把這個角色指派給一個新的 user:

指令
# [jmp001](管理員身分)
openstack role create c10-stu${NN}-compute -c name
openstack user create --domain Default --password "C10-Lab-${NN}" c10-stu${NN}-cu -c name
openstack role add --project c10-stu${NN} --user c10-stu${NN}-cu c10-stu${NN}-compute

預期輸出:

預期輸出
+-------+-------------------+
| Field | Value             |
+-------+-------------------+
| name  | c10-stu01-compute |
+-------+-------------------+
+-------+--------------+
| Field | Value        |
+-------+--------------+
| name  | c10-stu01-cu |
+-------+--------------+

用這個 user 取得 token,再試著列出 VM:

指令
# [jmp001]
bash
export OS_USERNAME=c10-stu${NN}-cu OS_PASSWORD=C10-Lab-${NN} OS_PROJECT_NAME=c10-stu${NN}
openstack token issue -c project_id
openstack server list
exit

預期輸出:

預期輸出
+------------+----------------------------------+
| Field      | Value                            |
+------------+----------------------------------+
| project_id | 677512d7cc3741ac8b417ad4129d407e |
+------------+----------------------------------+
ForbiddenException: 403: Client Error for url: http://10.127.0.250:8774/v2.1/servers/detail?deleted=False, Policy doesn't allow os_compute_api:servers:detail to be performed.