K8S容器編排之ConfigMap 用于動態(tài)應(yīng)用程序的實踐

導(dǎo)言:在 Kubernetes 中,ConfigMap 是允許管理員將配置組件與鏡像內(nèi)容解耦,使容器化應(yīng)用程序產(chǎn)生可移植性的一種資源。ConfigMap 可以與 Kubernetes Pod 一起使用,用于動態(tài)添加或更改容器中的使用文件。本文將闡述 Kubernetes ConfigMap 如何利用動態(tài)應(yīng)用程序的方法來解決輕量級文件服務(wù)器部署到 Kubernetes 集群中的問題。

ConfigMap 概覽

生產(chǎn)環(huán)境中很多應(yīng)用程序的配置可能需要通過配置文件、命令行參數(shù)和環(huán)境變量的組合來完成。這些配置應(yīng)該從鏡像中解耦,通過這種方式來保持容器化應(yīng)用程序的可移植性。在 Kubernetes 1.2 版本以后,研發(fā)人員引入 ConfigMap 來處理這種類型的配置數(shù)據(jù)。

簡單來說,ConfigMap 是容器的配置管理。在容器運行時,ConfigMap 把配置文件、命令行參數(shù)、環(huán)境變量、端口號和其他配置組件綁定到 Pod 的容器和系統(tǒng)組件上,同時將應(yīng)用的代碼和配置區(qū)分開。從數(shù)據(jù)角度來看,ConfigMap 的類型只是鍵值對。從應(yīng)用角度來看,管理員可以從不同角度來配置它。

在 Pod 中使用 ConfigMap 大致有以下三種方式:

  • 將 ConfigMap 中的數(shù)據(jù)設(shè)置為環(huán)境變量;
  • 將 ConfigMap 中的數(shù)據(jù)設(shè)置為命令行參數(shù);
  • 將 ConfigMap 作為文件或目錄掛載。
    另外,由于應(yīng)用會從環(huán)境變量和包含配置數(shù)據(jù)的文件中讀取配置信息,所以 ConfigMap 是可以支持這兩種讀取方式的。

創(chuàng)配置 ConfigMap 的注意事項

眾所周知,ConfigMapSecret 很相似。但是,ConfigMap 主要用來存儲和共享非敏感、未加密的配置信息。Secret 是用來存儲敏感信息(例如:密碼)。除了這個大家都了解的注意事項外,在配置 ConfigMap 時還要注意以下 4 點:

  • ConfigMap 必須在被 Pod 使用之前創(chuàng)建;
  • Pod 只能使用在同一 Namespace 中的 ConfigMap;
  • ConfigMap 大小的配額是一個已經(jīng)設(shè)置好的功能;
  • Kubelet 只支持 API 服務(wù)器中的 Pod 使用 ConfigMap。
    注:API 服務(wù)器中的 Pod 包括用 Kubectl 創(chuàng)建的 Pod、間接通過 replication controller 創(chuàng)建的 Pod,不包括通過 Kubelet 的 –manifest-url 標(biāo)志創(chuàng)建的 Pod,也不包括從它的 REST API 創(chuàng)建的 Pod。

ConfigMap 用于動態(tài)應(yīng)用程序的實踐

需要解決的問題

作為 Kubernetes 安裝程序的一部分,很多人希望可以將輕量級文件服務(wù)器部署到 Kubernetes 集群中以此處理默認(root - path)入口請求。并且,我認為如果我們可以編輯 index.html 和 CSS 文件而不必重新部署應(yīng)用程序。

為了解決這個用例,我們決定構(gòu)建一個 Golang 應(yīng)用程序,將其部分文件系統(tǒng)映射到 Kubernetes ConfigMap 資源中。

Golang Fileserver

文件服務(wù)器應(yīng)用程序的設(shè)計非常簡單,它僅用于提供靜態(tài)內(nèi)容。這種方式可以幫助 Kubernetes 用戶使用入口功能。

package main
import (
“l(fā)og”
“net/http”
)
func main() {
fs := http.FileServer(http.Dir(“html”))
http.Handle(“/”, fs)
log.Println(“Listening…”)
http.ListenAndServe(“:8080”, nil)
}

應(yīng)用程序使用以下 Dockerfile 內(nèi)容構(gòu)建容器鏡像。它是一個兩階段的 Dockerfile,首先在 Alpine 容器中執(zhí)行 Golang 構(gòu)建,然后將已編譯的二進制和空 helm 目錄復(fù)制到最終的 scratch-based 鏡像上。

# build stage  
FROM golang:alpine AS builder  
WORKDIR /usr/local/go/src  
COPY  main.go .  
RUN CGO_ENABLED=0 GOOS=linux go build -o main .  


# final stage  
FROM scratch  
WORKDIR /  
COPY --from=builder /usr/local/go/src/main main  
COPY html html  
EXPOSE 8080  
ENTRYPOINT ["/main"]

在 Golang 應(yīng)用程序中使用 scratch 容器來部署 Golang 容器是一種更安全、更輕量級的方法。

部署和運行

我使用 make 來自動化 Docker 操作。以下是此應(yīng)用程序的 Makefile 。

VERSION?= 0.0.1   
NAME?=“ingress-default”   
AUTHOR?=“Jimmy Ray”   
PORT_EXT?= 8080   
PORT_INT?= 8080    
NO_CACHE?= true   


.PHONY:build run stop clean   


build:   
docker build -f scratch.dockerfile.-t $(NAME)\:$(VERSION) -  no-cache = $(NO_CACHE)


run:   docker   
run --name $(NAME)-d -p $(PORT_EXT):$(PORT_INT)$(NAME) \:$(VERSION)&& docker ps -a --format“{{.ID}} \ t {{.Names}}”| grep $(NAME)   


stop:   
docker rm $$(docker stop $$(docker ps) -a -q --filter“ancestor = $(NAME):$(VERSION)” -  format =“{{.ID}}”))   

clean:   
@rm -f main   

DEFAULT:build

我們可以使用 make 消除重復(fù)任務(wù)之間的可變性。有了上述的 Makefile,在將測試的應(yīng)用程序部署到 Kubernetes 之前,我們可以在 Docker 中構(gòu)建和運行應(yīng)用程序。

配置 Kubernetes

對于此解決方案,我們需要配置 Kubernetes Namespace、ConfigMap、Deployment、Service 和 Ingress。我們通過使用 kubectl apply -f 的方法來完成此操作(這是對 Kubernetes 集群資源應(yīng)用更改的聲明式方法)。

下面是我們將 munge 的 Kubernetes 資源的 YAML 文件。

apiVersion: v1  
kind: Namespace  
metadata:  
  name: ingress-default 
  labels:  
    app: ingress-default  
---  
kind: ConfigMap  
apiVersion: v1  
metadata:  
  name: ingress-default-static-files  
  namespace: ingress-default   
  labels:  
    app: ingress-default   
data:  
  index.html: |  
    <!doctype html>  
    <html>  
      <head>  
        <meta charset="utf-8">  
        <title>Cluster Ingress Index</title>  
        <link rel="stylesheet" href="main.css">  
      </head>  
      <body>  
        <table class="class1">  
          <tr>  
            <td class="class2">Kubernetes Platform</td>  
          </tr>  
          <tr>  
            <td class="class1">  
              <table class="class3">  
                <tr><td><h1>Cluster Ingress Index</h1></td></tr>  
              </table>  
            </td>  
          </tr>  
          <tr>  
            <td>  
              <table class="class3">  
                <tr>  
                <td>  
                   <h2>The following are links to this cluster's ingress resources:</h2>  
                  </td>  
                </tr>  
                <tr>  
                <td class="class4">  
                    <a href="https://<ROOT_INGRESS_PATH>" target="_blank">Root Ingress</a><br/>  
                    <a href="https://<OTHER_INGRESS_PATH>" target="_blank">Other Ingress</a><br/>   
                 </td>  
               </tr>  
              </table>  
            </td>  
          </tr>  
         </table>  
      </body>  
    </html>  
  main.css: |  
    body {  
      background-color: rgb(224,224,224);  
      font-family: Verdana, Arial, Helvetica, sans-serif;  
      font-size: 100%;  
    }  
    .class1 {  
  ... 
    }  
    .class2 {  
  ... 
    }  
    .class3 {  
  ... 
    }  
    .class4 {  
     ...
    }   
---  
apiVersion: apps/v1  
kind: Deployment  
metadata:  
  labels:  
    app: ingress-default   
  name: ingress-default  
  namespace: ingress-default 
spec:  
  selector:  
    matchLabels:  
      app: ingress-default  
  replicas: 1  
  template:  
    metadata:  
      labels:  
        app: ingress-default    
      name: ingress-default  
    spec:  
      containers:  
        - name: ingress-default  
          image: <IMAGE_REGISTRY_REPO_TAG>  
          imagePullPolicy: Always  
          resources:  
            limits:  
              cpu: 100m  
              memory: 10Mi  
            requests:  
              cpu: 100m  
              memory: 10Mi  
          volumeMounts:  
            - readOnly: true  
              mountPath: html  
              name: html-files  
      volumes:  
        - name: html-files  
          configMap:  
            name: ingress-default-static-files  
---  
kind: Service  
apiVersion: v1  
metadata:  
  name: ingress-default  
  namespace: ingress-default  
  labels:  
    app: ingress-default  
spec:  
  selector:  
    app: ingress-default  
  ports:  
  - name: http  
    protocol: TCP  
    port: 80  
    targetPort: 8080  
---  
apiVersion: extensions/v1beta1  
kind: Ingress  
metadata:  
  name: default-ingress  
  namespace: ingress-default  
  annotations:   
    nginx.ingress.kubernetes.io/rewrite-target: /  
    kubernetes.io/ingress.class: "nginx"    
  labels:  
    app: ingress-default  
spec:  
  rules:  
  - http:  
      paths:  
      - path: /  
        backend:  
          serviceName: ingress-default  
          servicePort: 80

正如在 YAML 中的:

ingress-default-static-files

我們可以知道,ConfigMap 包含index.html 和 main.css 文件的內(nèi)容。通過編輯或替換此 ConfigMap,我們可以更改在 Golang 文件服務(wù)器應(yīng)用程序中的文件。

使用 ConfigMap 作為卷

在 Docker 和 Kubernetes 的中,卷用于解決兩個問題:

  • 需要持久化的文件系統(tǒng);
  • 需要在容器之間共享的文件系統(tǒng)。
    現(xiàn)在,我們將已部署在容器中的卷映射到 ConfigMap 資源中。在下面的代碼段中,被配置的 html-files 卷可能被 Pod 中的所有容器使用。

卷會將數(shù)據(jù)配置映射到 ConfigMap 中的 ingress-default-static-files 上。

...volumes:  
     - name: html-files  
       configMap:  
         name: ingress-default-static-files…

在 Pod 級別配置卷后,我們將配置的卷裝入容器中。將此卷的掛載映射到在 Pod 中配置的 html-files 卷上。通過此映射,應(yīng)用程序容器現(xiàn)在可以訪問 ConfigMap 中的兩個文件:html/index.html 和 html/mian.css。

...volumeMounts:  
     - readOnly: true  
       mountPath: html  
       name: html-files 

當(dāng)在 Kubernetes 集群中啟動 Golang 應(yīng)用程序時,ingress-default 會在 NGINX 入口控制器中配置上游規(guī)則。生成的路徑將通過 NGINX 入口控制器將集群邊緣連接到ingress-default 服務(wù)上。此服務(wù)指向 Golang 文件服務(wù)的 app Pod 中。在運行時,它為 ingress 控制器的根路徑上的默認 Web 應(yīng)用程序提供服務(wù)。如果需要更改此網(wǎng)頁,我們只需要 edit/replace ConfigMap。

結(jié)語

容器編排的一個關(guān)鍵好處是,它承諾消除多個容器工作負載所需的“無差異的繁重工作”。通過使用 Kubernetes 聲明性配置功能(如 ConfigMap),可以提高應(yīng)用程序部署和更改集群狀態(tài)的效率與速度。我們通過將 ConfigMap 資源作為已安裝的卷,使用正在運行的容器,可以從容器中抽象配置和內(nèi)容,減少對鏡像重構(gòu)和重新部署容器的需求。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1、基礎(chǔ)架構(gòu) 1.1 Master Master節(jié)點上面主要由四個模塊組成:APIServer、scheduler...
    阿斯蒂芬2閱讀 11,148評論 0 44
  • 一、 K8s 是什么? Kubernetes(k8s)是自動化容器操作的開源平臺,這些操作包括部署,調(diào)度和節(jié)點集群...
    loveroot閱讀 6,711評論 1 21
  • 我只愿與朋友如水般相處 朋友袁的父親去世,我知道的第一時間打了電話。不久一個通過我認識袁,并與袁有一些人情來往的靜...
    天邊微云閱讀 405評論 4 6
  • 從來沒有如此無辜, 落寞中還添酸楚。 初起的那刻花飛舞, 花城偶遇的我們, 和聲陽春白雪, 在歲月里同步。 幾季雨...
    狐落云端閱讀 1,552評論 41 35
  • “我在我的繪畫中創(chuàng)造一切?!薄?塔西娜·亞瑪瑞 她是誰? 她的《食人者》之于巴西的意義,不亞于《蒙娜麗莎》...
    泡芙兮閱讀 1,066評論 0 1

友情鏈接更多精彩內(nèi)容