iT邦幫忙

2022 iThome 鐵人賽

DAY 18
2
DevOps

從異世界歸來發現只剩自己不會 Kubernetes系列 第 18

從異世界歸來的第十八天 - Kubernetes Volume (三) - ConfigMap

  • 分享至 

  • xImage
  •  

概述

在正式環境中的產品開發中,大多人都會遇到不同環境的佈署,最簡單的會被分成開發環境(Development)以及正式環境(Production),這時區分這些環境的關鍵往往是連線的資料庫或是使用的 Token 、 ApiKey 或是初始化資料等等,這些被抽離出來的設定(Configuration)很好的降低了程式碼的耦合,讓我們只需要簡單的編輯一下相關設定檔即可創造出我們想要的相對環境,而 Kubernetes 提供了 ConfigMap 讓我們可以從最頂層方便的向下注入。

ConfigMap 的特性

基本上 ConfigMap 可以理解為存放設定檔的功能,也就是說這個物件可以直接連接一個或多個檔案,在我們程式中需要的地方可以使其被取用。

  • 一個 ConfigMap 物件可以存入一個或多個設定檔。
  • 降低程式碼耦合,同一份代碼只需抽換不同的 ConfigMap 即可切換不同環境。
  • 統一存放所有設定檔,在 Kubernetes 中可以統一查看以及管理。

建立 ConfigMap

簡單介紹建立一個 ConfigMap 的幾種方式:

1. 用指令匯入整個檔案 :

# 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
);

CREATE INDEX user_id_key ON posts (user_id);

COMMENT ON COLUMN posts.title IS '標題';
    COMMENT ON COLUMN posts.content IS '內容';
    COMMENT ON COLUMN posts.comments_count IS '評論數';
kubectl create configmap pg-initsql --from-file=initdb.sql
--------
configmap/pg-initsql createdg-initsql

利用 kubectl create 指令將整個檔案設定成一個 configMap

查看一下產生結果:

kubectl describe configmap pg-initdb
---------
Name:         pg-initdb
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
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
);

CREATE INDEX user_id_key ON posts (user_id);

COMMENT ON COLUMN posts.title IS '標題';
    COMMENT ON COLUMN posts.content IS '內容';
    COMMENT ON COLUMN posts.comments_count IS '評論數';

BinaryData
====

2. 使用指令建立 key-value 組合:

kubectl create configmap pg-connect \
--from-literal=host=127.0.0.1 \
--from-literal=port=5432

以上我們使用指令建立 host port 兩組 key-value。

查看一下結果:

kubectl describe configmap pg-connect
----------
Name:         pg-connect
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
host:
----
127.0.0.1
port:
----
5432

BinaryData
====

3. 使用 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,
        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
    );
    
    CREATE INDEX user_id_key ON posts (user_id);
    
    COMMENT ON COLUMN posts.title IS '標題';
    COMMENT ON COLUMN posts.content IS '內容';
    COMMENT ON COLUMN posts.comments_count IS '評論數';
kubectl apply -f initdb-configmap.yaml
---------
configmap/post-initdb-yaml created

查看一下結果:

kubectl describe configmap initdb-yaml
---------
Name:         initdb-yaml
Namespace:    default
Labels:       app=db
Annotations:  <none>

Data
====
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
);

CREATE INDEX user_id_key ON posts (user_id);

COMMENT ON COLUMN posts.title IS '標題';
COMMENT ON COLUMN posts.content IS '內容';
COMMENT ON COLUMN posts.comments_count IS '評論數';

BinaryData
====

4. 使用 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

查看一下結果:

kubectl describe configmap initdb-kv-yaml
--------
Name:         initdb-kv-yaml          
Namespace:    default
Labels:       app=db
Annotations:  <none>

Data
====
PG_PASSWORD:
----
postgres
PG_USER:
----
postgres

BinaryData
====

實際應用 Config

# 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
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: initdb
  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,
        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
    );
    
    CREATE INDEX user_id_key ON posts (user_id);
    
    COMMENT ON COLUMN posts.title IS '標題';
    COMMENT ON COLUMN posts.content IS '內容';
    COMMENT ON COLUMN posts.comments_count IS '評論數';
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: initdb-kv-yaml
  labels:
    app: db
data:
  PG_USER: PG_USER
  PG_PASSWORD: PG_USER
kubectl apply -f pg-pod.yaml,initdb-kv.yaml
-----------
pod/db created
configmap/initdb created
configmap/initdb-kv-yaml unchanged

在上面的設定中我們同時利用的 ConfigMap 的檔案掛載以及 key-value 掛載,設定了我們的 postgres 初始化資料表以及使用者帳號密碼。

接下來我們來驗證一下是否設定都已成功注入到 postgres 中:

進入容器:

kubectl exec -it db -- sh

ls
---------
bin                         etc                         media                       proc                        sbin                        tmp
dev                         home                        mnt                         root                        srv                         usr
docker-entrypoint-initdb.d  lib                         opt                         run                         sys                         var

成功進入 postgres 即可使用 psq cli 操作。

檢查 initdb.sql 是否成功掛載:

cat docker-entrypoint-initdb.d/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
);

CREATE INDEX user_id_key ON posts (user_id);

COMMENT ON COLUMN posts.title IS '標題';
COMMENT ON COLUMN posts.content IS '內容';
COMMENT ON COLUMN posts.comments_count IS '評論數';

成功獲得 ConfigMap 檔案。

檢查 Role 是否被成功創立:

在剛剛的 postgres 容器中,使用 psql cli 登入:

psql -U PG_USER -d posts
-------
psql (12.4)
Type "help" for help.

posts=#

成功以我們設定的帳號名稱 PG_USER 以及資料庫 posts 登入。

檢查是否成功建立資料表 Posts

posts=# \d posts
                                          Table "public.posts"
     Column     |            Type             | Collation | Nullable |              Default              
----------------+-----------------------------+-----------+----------+-----------------------------------
 id             | bigint                      |           | not null | nextval('posts_id_seq'::regclass)
 uuid           | character varying(36)       |           | not null | 
 user_id        | numeric                     |           | not null | 
 title          | character varying(255)      |           | not null | 
 content        | text                        |           | not null | 
 comments_count | numeric                     |           |          | 0
 created_at     | timestamp without time zone |           | not null | now()
 updated_at     | timestamp without time zone |           | not null | now()
 deleted_at     | timestamp without time zone |           |          | 
Indexes:
    "posts_pkey" PRIMARY KEY, btree (id)
    "posts_uuid_key" UNIQUE CONSTRAINT, btree (uuid)
    "user_id_key" btree (user_id)

大功告成~

結論

今天我們實作了 ConfigMap 最常見的兩種使用方式,在官方文件中 ConfigMap 還有其他更進階的操作方式,這裡就先簡單介紹可以應付多數應用場景的方法。


狂賀₍₍ ◝( ゚∀ ゚ )◟ ⁾⁾♪

千呼萬喚始出來!鐵人賽系列「從異世界歸來發現只剩自己不會 Kubernetes」同名改編作品出版了!
感謝所有交流指教的各路英雄,也感謝願意點閱文章的各位,如果能幫助到任何人都將會是我的榮幸。

本書內容改編自第 14 屆 iThome 鐵人賽 DevOps 組的優選系列文章《從異世界歸來發現只剩自己不會 Kubernetes》。此書是一本綜合性的指南,針對想要探索認識 Kubernetes 的技術人員而生。無論是初涉此領域的新手,還是已有深厚經驗的資深工程師,本書都能提供你所需的知識和技能。

「這本書不僅提供了豐富的範例程式碼和操作指南,讓身為工程師的我們能實際操作來加深認知;更重要的是,它教會我如何從後端工程師的角度去思考和應用 Kubernetes。從容器的生命週期、資源管理到部署管理,每一章都與我們的日常開發工作息息相關。」
──── 雷N │ 後端工程師 / iThome 鐵人賽戰友

天瓏連結: 從異世界歸來發現只剩自己不會 Kubernetes:初心者進入雲端世界的實戰攻略!
https://ithelp.ithome.com.tw/upload/images/20231030/201495629BWPC1wajW.png


相關文章:

相關程式碼同時收錄在:

https://github.com/MikeHsu0618/2022-ithelp/tree/master/Day18

Reference

配置Pod 使用ConfigMap

[Day 18] 高彈性部署 Application - ConfigMap

Kubernetes 那些事 — ConfigMap 與 Secrets


上一篇
從異世界歸來的第十七天 - Kubernetes Volume (二) - EmptyDir
下一篇
從異世界歸來的第十九天 - Kubernetes Volume (四) - Secret
系列文
從異世界歸來發現只剩自己不會 Kubernetes30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
tytom2005
iT邦新手 5 級 ‧ 2024-07-12 14:26:52

在"建立 ConfigMap", "1. 用指令匯入整個檔案 :",執行"kubectl create configmap pg-initsql --from-file=initdb.sql", 但是第二行kubectl describe configmap pg-initdb,不是"kubectl describe configmap pg-initsql"?

kubectl describe configmap initdb-kv-yaml 裏name: initdb-kv-yaml initdb-kv-yaml 是不是重複了?

請問pg-initdb, pg-connect, initdb-yaml到最後,是在那裏使用?

請問"實際應用 Config" 裏的"pg-pod.yaml":
apiVersion: v1
kind: ConfigMap
metadata:
name: initdb-kv-yaml
labels:
app: db
data:
PG_USER: PG_USER
PG_PASSWORD: PG_USER

這裏是引用initdb-kv-yaml 的使用名稱和密碼在create Pod和 ConfigMap裏使用?

在"4. 使用 yaml 檔建立 key-value:"漏了執行"kubectl apply -f initdb-kv-configmap.yaml" 去create configmap 指令

這裡主要介紹實務使用場景,感謝指正~
initdb-kv-yaml 是用來將環境變數透過 configmap keyref 注入到容器當中。

      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

我要留言

立即登入留言