自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

摸魚心法第一章——和配置文件說拜拜

開發(fā) 前端
從本地開發(fā)和容器運(yùn)行兩個角度來看,本地開發(fā)的時候讀取配文件比讀取環(huán)境變量方便,容器運(yùn)行中讀取環(huán)境變量比讀取配置文件方便,我想說你倆擱這卡bug呢?

為了能摸魚我們團(tuán)隊做了容器化,但是帶來的問題是服務(wù)配置文件很麻煩,然后大家在群里進(jìn)行了“親切友好”的溝通

圖片圖片

圖片圖片

圖片圖片

圖片圖片

對比就對比,簡單對比下獨(dú)立配置中心和k8s作為配置中心的區(qū)別


獨(dú)立配置中心

k8s作為配置中心

學(xué)習(xí)成本

1.運(yùn)維要學(xué)習(xí)搭建、維護(hù)

2.研發(fā)和研發(fā)都需要學(xué)習(xí)配置中心的工具、系統(tǒng)如何使用

1.熟悉yaml/json語法即

2.研發(fā)只需要解析環(huán)境變量,無需關(guān)注注入細(xì)節(jié)

適配工作量

  1. 代碼需要引入對應(yīng)配置中心的庫進(jìn)行開發(fā)
  2. 需要在對應(yīng)的配置中心管理

  1. 服務(wù)直接解析環(huán)境變量即可
  2. k8s原生支持環(huán)境變量,并且支持通過configmap,secret資源注入到服務(wù)的環(huán)境變量中

集群維護(hù)成本

額外維護(hù)成本

保證集群etcd穩(wěn)定即可,無額外成本

服務(wù)發(fā)現(xiàn)

支持服務(wù)發(fā)現(xiàn)

支持服務(wù)發(fā)現(xiàn)

云資源費(fèi)用

增加成本

無額外成本

對比結(jié)果出來后,群里的研發(fā)也覺得k8s作為配置中心不錯了

圖片圖片

圖片圖片

我這里想問問在看文章的同學(xué):是不是都覺得運(yùn)維的東西很簡單?還有是不是個鍋都甩給運(yùn)維?像這樣的研發(fā)你身邊多么還是說你也是這樣的研發(fā)? 

繼續(xù)今天的話題,既然服務(wù)要在k8s里運(yùn)行,同時也要把k8s作為配置中心使用,那服務(wù)適配需要做些啥? 咱們先列一個清單

圖片圖片

服務(wù)要優(yōu)雅的適配容器化環(huán)境,需要解決以下問題

  • 避免繁瑣的定義和解析服務(wù)環(huán)境變量
  • 服務(wù)在本地調(diào)試下和容器環(huán)境運(yùn)行兩種場景下,對于環(huán)境變量的解析需要無縫切換
  • 服務(wù)的dockerfile可根據(jù)服務(wù)信息自動生成,盡量避免人工操作

1.首先說環(huán)境變量的問題

從本地開發(fā)和容器運(yùn)行兩個角度來看,本地開發(fā)的時候讀取配文件比讀取環(huán)境變量方便,容器運(yùn)行中讀取環(huán)境變量比讀取配置文件方便,我想說你倆擱這卡bug呢?

但是這個問題其實(shí)不難,解決邏輯也很簡單。那就是采用覆寫的思路,如果環(huán)境變量里讀取到了值就用環(huán)境變量的,否則就用代碼里的值。

那按照這個思路是得有一個配置文件,然后服務(wù)讀取這個配置文件?可惜這個和我們團(tuán)隊的一個追求相違背——代碼及文檔

說到文檔,插個題外話,對于寫文檔這事兒。。。

看別人的東西,你TM文檔呢? 

做自己的東西,這TM還用寫文檔?

回到環(huán)境變量這個問題來,其實(shí)在代碼里面定義變量并提供覆寫的能力就足夠了??紤]到在本地開發(fā)調(diào)試的時候,需要頻繁修改變量的值,無論是修改代碼里的變量值或者修改環(huán)境變量還是稍顯麻煩,所以覆寫的信息可以來源于環(huán)境變量或一個覆寫的變量文件

流程如下

圖片圖片

針對提供反射機(jī)制的編程語言結(jié)合一定的規(guī)則,環(huán)境變量的key可以直接從定義的結(jié)構(gòu)體里獲取無需額外維護(hù)。無反射類型的編程語言也可以按照這個思路實(shí)現(xiàn),只是稍顯麻煩。這樣環(huán)境變量的問題解決了,然后就是dockerfile的問題

2.dockerfile如何自動生成

我們再看看剛才列的清單

圖片圖片

首先說說核心問題如何編譯,有兩種方式

1.直接在dockerfile里面寫編譯過程

直接手寫dockerfile沒有問題,因?yàn)榉?wù)的開發(fā)人員最清楚自己的服務(wù)需要怎么編譯,但是不同的服務(wù)總會出現(xiàn)差異化的編譯過程,這樣從代碼自動生成dockerfile的角度來講不可控

2.makefile文件

通過makefile來執(zhí)行編譯步驟就解決了差異化的問題,在dockerfile里只需要執(zhí)行類似make build的固定命令便完成了服務(wù)編譯全過程。自動化工具按照固定的dockerfile模板生成文件,makefile完成具體的編譯過程,這樣服務(wù)編譯與工具完美解耦

核心問題解決了,至于dockerfile如何生成,每種編程語言都可以采用自身語言提供的模板庫進(jìn)行生成dockerfile了。即便不用模板,拼接字符串也是可以的,條條大路通羅馬。

然后我們再談?wù)劄槭裁磿芯幾g鏡像和運(yùn)行鏡像的區(qū)別,我們看看下面這個流程

圖片圖片

從流程可以看出,服務(wù)在k8s里面啟動時會從鏡像倉庫拉去服務(wù)鏡像,這里存在一個網(wǎng)絡(luò)傳輸?shù)膯栴},內(nèi)網(wǎng)都不說了,如果從公網(wǎng)拉鏡像,并發(fā)量高一點(diǎn),拉的再頻繁點(diǎn),不管是固定帶寬還是按流量計費(fèi),老話說得好,這不就是小刀剌了貔貅腚——拉的都是錢

所以我們期望的是鏡像足夠小,這樣在部署服務(wù)的時候更快更省錢,尤其是首次部署的時候(這里涉及到docker 分層的問題不做展開)。編譯鏡像一般都非常龐大并不適合作為運(yùn)行鏡像使用,只需要提供編譯環(huán)境,編譯完成后將編譯后的文件放入一個很小的運(yùn)行鏡像中即可

以我們團(tuán)隊采用的是Golang語言為例,編譯鏡像目前采用的1.20.5-buster,AMD64的鏡像大小為275M,ARM的鏡像大小為264M,運(yùn)行鏡像采用的是gcr.io/distroless/static-debian11,最終運(yùn)行鏡像大小在20M左右,這不得起飛了啊,拉鏡像就跟玩兒一樣。

好了,今天的文章主要分享了在容器化環(huán)境下,通過拋棄服務(wù)配置文件而采用環(huán)境變量的形式來解決配置注入的問題,自動生成dockerfile需要避免的坑,希望對在走容器化道路的同學(xué)有所幫助。如果大家想聽聽其他的可以留言或者私信我們。

接下來就是Golang的福利時間,我們將這個變量注入的庫進(jìn)行了開源?,F(xiàn)在用gin框架寫個demo來演示環(huán)境變量注入和生成dockerfile。(我們在gin框架上加了一點(diǎn)點(diǎn)東西,這樣更好用)

首先創(chuàng)建一個工程目錄

圖片圖片

global/config.go這個文件長這樣

package global


import (
  "github.com/kunlun-qilian/conflogger"
  "github.com/kunlun-qilian/confserver"
  "github.com/kunlun-qilian/confx"
)


func init() {
  confx.SetConfX("demo-docker", "..")
  confx.ConfP(&Config)
}


var Config = struct {
  Logger  *conflogger.Log
  Server  *confserver.Server
  TestEnv string `env:""`# 環(huán)境變量標(biāo)記,只要有這個標(biāo)記則支持注入
}{
  Server: &confserver.Server{
    Port: 80,
    Mode: "debug",
  },
  TestEnv: "123",
}
github.com/kunlun-qilian/confx
這個庫的作用就是注入環(huán)境變量和生成dockerfile,
單獨(dú)出來了一個庫,只要是這個工程目錄結(jié)構(gòu)都可以使用

運(yùn)行之后會生成config/default.yml,這個環(huán)境變量文件就是每次啟動服務(wù)后根據(jù)上述global/config.go文件自動生成的默認(rèn)配置文件,這個文件是作為后續(xù)本地覆寫配置文件的藍(lán)本,免得不知道環(huán)境變量是啥,環(huán)境變量規(guī)則是“服務(wù)名__環(huán)境變量名”

DEMO_DOCKER__Logger_Level: ""
DEMO_DOCKER__Logger_Output: Always
DEMO_DOCKER__Server_Mode: debug
DEMO_DOCKER__Server_UseH2C: "false"
DEMO_DOCKER__TestEnv: "123"

demo里加入了一個接口來返回TestEnv的值

圖片圖片

在本地開發(fā)的時候需要覆寫默認(rèn)值的時候,只需要在config目錄下加入一個叫做 local.yml(這個放gitignore里)的文件并添加想替換的值

圖片圖片

重新運(yùn)行一下服務(wù),再看接口,變量被local.yml里面的值替換了

圖片圖片

然后我們再通過當(dāng)前命令行會話中注入一個環(huán)境變量,然后啟動

export DEMO_DOCKER__TestEnv=terminal_789 && go run main.go

值又被替換成了環(huán)境變量的值,有了這個還要啥自行車?

圖片圖片


再看看生成的dockerfile,下面這個就是自動生成的默認(rèn)dockerfile

FROM dockerproxy.com/library/golang:1.20-buster AS build-env


FROM build-env AS builder




WORKDIR /go/src
COPY ./ ./


# build
RUN make build WORKSPACE=demo-docker


# runtime
FROM gcr.dockerproxy.com/distroless/static-debian11


COPY --from=builder /go/src/cmd/demo-docker/demo-docker /go/bin/demo-docker




EXPOSE 80


ARG PROJECT_NAME
ARG PROJECT_VERSION
ENV PROJECT_NAME=${PROJECT_NAME} PROJECT_VERSION=${PROJECT_VERSION}


WORKDIR /go/bin
ENTRYPOINT ["/go/bin/demo-docker"]

上文中提到的幾個配置信息,咱們定義了一個結(jié)構(gòu),包含了編譯鏡像,運(yùn)行鏡像,GOPROXY代理,openapi文件,奧,差點(diǎn)忘了這篇不涉及到openapi,篇幅有限這個在后續(xù)篇章里講,你們懂的

type DockerConfig struct {
  BuildImage   string
  RuntimeImage string
  GoProxy      GoProxyConfig
  Openapi      bool
}


type GoProxyConfig struct {
  ProxyOn bool
  Host    string
}

在global/config.go中的init方法中,留了入口

func init() {
  confx.SetConfX("demo-docker", "..", confx.DockerConfig{
    BuildImage:   "private-harbor.xxx.com/xxx/builder:v1.0.0",
    RuntimeImage: "private-harbor.xxx.com/xxx/runtime:v1.0.0",
    GoProxy: confx.GoProxyConfig{
      ProxyOn: true,
      Host:    "https://goproxy.cn,direct",
    },
  })
  confx.ConfP(&Config)
}

然后我們再重新運(yùn)行一下看看結(jié)果,編譯鏡像、運(yùn)行鏡像、代理都更新了

FROM private-harbor.xxx.com/xxx/builder:v1.0.0 AS build-env


FROM build-env AS builder




ARG GOPROXY=https://goproxy.cn,direct


WORKDIR /go/src
COPY ./ ./


# build
RUN make build WORKSPACE=demo-docker


# runtime
FROM private-harbor.xxx.com/xxx/runtime:v1.0.0


COPY --from=builder /go/src/cmd/demo-docker/demo-docker /go/bin/demo-docker




EXPOSE 80


ARG PROJECT_NAME
ARG PROJECT_VERSION
ENV PROJECT_NAME=${PROJECT_NAME} PROJECT_VERSION=${PROJECT_VERSION}


WORKDIR /go/bin
ENTRYPOINT ["/go/bin/demo-docker"]

如果服務(wù)有多個端口怎么處理?還是從global/config.go中下手,增加一個 TestPort 的變量,tag中加上 `env:"opt,expose"`

var Config = struct {
  Logger  *conflogger.Log
  Server  *confserver.Server
  TestEnv string `env:""`


  TestPort int `env:"opt,expose"` # 看這里,看這里
}{
  Server: &confserver.Server{
    Port: 80,
    Mode: "debug",
  },
  TestEnv:  "123",
  TestPort: 9090,
}

然后咱們再運(yùn)行一次,9090端口暴露出來了,這帶手表了,帶啥手表了?

FROM private-harbor.xxx.com/xxx/builder:v1.0.0 AS build-env


FROM build-env AS builder




ARG GOPROXY=https://goproxy.cn,direct


WORKDIR /go/src
COPY ./ ./


# build
RUN make build WORKSPACE=demo-docker


# runtime
FROM private-harbor.xxx.com/xxx/runtime:v1.0.0


COPY --from=builder /go/src/cmd/demo-docker/demo-docker /go/bin/demo-docker




EXPOSE 9090


EXPOSE 80


ARG PROJECT_NAME
ARG PROJECT_VERSION
ENV PROJECT_NAME=${PROJECT_NAME} PROJECT_VERSION=${PROJECT_VERSION}


WORKDIR /go/bin
ENTRYPOINT ["/go/bin/demo-docker"]

最后貼上全球最大同。。不對,是github鏈接,后續(xù)我們還會逐步開源一些工具

工具包c(diǎn)onfx: https://github.com/kunlun-qilian/confx
本文的demo:  https://github.com/kunlun-qilian/gin-demo


責(zé)任編輯:武曉燕 來源: 佳華云原生實(shí)踐
相關(guān)推薦

2014-01-13 11:22:28

storm

2015-12-30 09:25:47

編程故事printf

2012-02-09 10:39:37

AndroidWeb App官方文檔

2011-07-19 17:25:14

jQuery MobiAndroid

2011-07-20 10:27:18

jQuery Mobi手機(jī)新聞瀏覽器

2023-05-24 16:13:31

ChatGPT神經(jīng)網(wǎng)絡(luò)

2013-10-15 14:18:31

2009-02-25 09:20:42

職場調(diào)查壓力

2023-08-10 09:44:38

YAML文件環(huán)境

2010-12-07 10:40:27

軟考系統(tǒng)架構(gòu)設(shè)計師

2022-11-11 08:16:51

2017-05-28 12:26:58

5GTCPIP

2012-10-12 13:35:51

Windows 8

2010-12-28 10:55:07

PC技術(shù)

2010-12-13 11:50:48

三級PC技術(shù)

2011-01-04 13:51:44

PC技術(shù)

2010-12-09 10:59:54

三級PC技術(shù)

2011-01-21 15:08:45

Sendmail

2012-05-28 13:56:41

Web

2009-06-24 14:17:00

BackingBeanJSF配置文件
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號