為什麼需要 ConfigMap#
實務開發中,最常見的多環境部署莫過於開發(Development)與正式(Production)兩個環境。決定環境差異的,往往是這些設定:
- 連線的資料庫位址與帳密。
- API Token、API Key。
- 資料初始化腳本與其他組態。
把這些設定從程式碼中抽離,可以降低耦合:同一份程式碼只要切換設定檔,就能切換環境。Kubernetes 提供 ConfigMap 讓這件事可以從叢集最頂層方便地向下注入。
ConfigMap 的特性#
- 一個 ConfigMap 物件可以存放一個或多個設定檔。
- 切換環境時不必動程式碼,只要切換對應的 ConfigMap。
- 所有設定統一存放於 Kubernetes 中,便於查看與管理。
建立 ConfigMap 的幾種方式#
1. 用 kubectl 從檔案匯入#
先準備一個 SQL 初始化腳本:
-- initdb.sql
DROP TABLE IF EXISTS posts CASCADE;
CREATE TABLE posts
(
id BIGSERIAL PRIMARY KEY,
uuid VARCHAR(36) NOT NULL UNIQUE,
user_id NUMERIC NOT NULL,
title VARCHAR(255) NOT NULL,
content TEXT NOT NULL,
comments_count NUMERIC DEFAULT 0,
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
updated_at TIMESTAMP NOT NULL DEFAULT NOW(),
deleted_at TIMESTAMP NULL
);把整個檔案做成 ConfigMap:
kubectl create configmap pg-initdb --from-file=initdb.sql
kubectl create與kubectl apply的差異:前者明確告訴 Kubernetes 要建立一個資源;後者通常搭配 yaml 設定檔,描述「資源最終應該長什麼樣」。
確認結果:
kubectl describe configmap pg-initdb2. 用指令直接建立 key-value#
kubectl create configmap pg-connect \
--from-literal=host=127.0.0.1 \
--from-literal=port=5432可以一次塞多組 key-value,使用 kubectl describe 即可看到結果:
Data
====
host:
----
127.0.0.1
port:
----
54323. 用 yaml 把整個檔案內容寫進來#
# initdb-configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: initdb-yaml
labels:
app: db
data:
initdb.sql: |
DROP TABLE IF EXISTS posts CASCADE;
CREATE TABLE posts (
id BIGSERIAL PRIMARY KEY,
uuid VARCHAR(36) NOT NULL UNIQUE,
-- ... 其餘欄位省略,與前面 initdb.sql 相同
);kubectl apply -f initdb-configmap.yaml4. 用 yaml 建立 key-value#
# initdb-kv.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: initdb-kv-yaml
labels:
app: db
data:
PG_USER: postgres
PG_PASSWORD: postgres在 Pod 中使用 ConfigMap#
下面範例同時示範兩種典型的注入方式:
- 用
valueFrom.configMapKeyRef把某個 key 注入為環境變數。 - 用
volumes.configMap把整個 ConfigMap 當作檔案掛載到容器內。
# pg-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: db
labels:
app: db
spec:
containers:
- name: db
image: postgres:12.4-alpine
env:
# 使用 configmap 的 key-value 做為值傳入
- name: POSTGRES_USER
valueFrom:
configMapKeyRef:
name: initdb-kv-yaml
key: PG_USER
- name: POSTGRES_PASSWORD
valueFrom:
configMapKeyRef:
name: initdb-kv-yaml
key: PG_PASSWORD
- name: PGDATA
value: "/var/lib/postgresql/data/pgdata"
- name: POSTGRES_DB
value: "posts"
ports:
- containerPort: 5432
volumeMounts:
# 使用 configmap 做為 file 當作初始化設定
- mountPath: /docker-entrypoint-initdb.d
name: initdb
volumes:
- name: initdb
configMap:
name: initdb部署:
kubectl apply -f pg-pod.yaml驗證注入結果#
進入容器:
kubectl exec -it db -- sh確認 SQL 檔案是否成功掛載:
cat docker-entrypoint-initdb.d/initdb.sql確認帳號被當作環境變數帶入並建立:
psql -U PG_USER -d posts進入 psql 後檢查表格是否正確建立:
posts=# \d posts可以看到 posts 表的所有欄位都依照 initdb.sql 建立完成。
小結#
本章示範了 ConfigMap 最常見的兩種用法:
- 以「環境變數」的方式注入個別 key-value。
- 以「檔案掛載」的方式把整份設定提供給容器使用。
在多數應用場景中,這兩種方法已經足以支撐多環境的設定切換。官方還有更進階的功能(例如 SubPath、optional、自動更新等),可以在熟悉基本用法後再深入研究。
原文出處#
- GitHub:https://github.com/MikeHsu0618/2022-ithelp/tree/main/Day18
- iThome:https://ithelp.ithome.com.tw/articles/10293127