老大給我7天讓我將項(xiàng)目從SpringCloud改造到K8S

之前項(xiàng)目使用的是springcloud,主要使用到的組件有 spring gateway, nacos, minio, load balancer,open-feign等,然后我們的微服務(wù)通過(guò)docker部署到虛擬機(jī)里面的。

但是出于安全的考慮,需要將它遷移到azure的aks(kubernetes)中,所以需要將spring cloud改造成spring boot姻檀。這樣就不用自己維護(hù)虛擬機(jī)的安全策略吊圾,也不需要去關(guān)注補(bǔ)丁了春感。

梳理項(xiàng)目結(jié)構(gòu)

項(xiàng)目是一個(gè)一個(gè)微服務(wù)組織起來(lái)的绊袋,大概業(yè)務(wù)類的服務(wù)有5個(gè),公共服務(wù)有4個(gè)。 設(shè)計(jì)到的改造主要集中在gateway, auth中度硝,公共包的一些改造比較少实蔽,主要是將open-feign的訪問(wèn)改為通過(guò)url進(jìn)行調(diào)用,而不是之前通過(guò)服務(wù)名來(lái)。

而在kubernetes中均践,我們使用Traefik2來(lái)代替gateway的功能晤锹,不知道traefik2的,可以去翻翻之前的文章彤委。

同時(shí)對(duì)于授權(quán),需要提供一個(gè)授權(quán)接口鞭铆,配合traefik2使用,這樣每一個(gè)請(qǐng)求都會(huì)進(jìn)行授權(quán)的驗(yàn)證焦影。

開(kāi)始改造

確定分支

最開(kāi)始肯定是新拉一個(gè)分支進(jìn)行這些改動(dòng)车遂,即便沒(méi)改好也不影響其他人,所以我們先把分支名定好就叫做 feature/AKS-migrate斯辰。

改造gateway

首先把pom文件中的不需要的依賴包注釋掉,比如spring cloud gateay, nacos, sentinel等spring cloud相關(guān)組件舶担。注釋掉之后
去看代碼中有哪些報(bào)錯(cuò),就針對(duì)性的修改彬呻。

我們的項(xiàng)目中使用蠻多gateway的filter以及handler,最開(kāi)始我看他們都是使用的webflux,我就想我單獨(dú)引入這個(gè)包衣陶,代碼是不是最小的改動(dòng)就行了呢?

這樣嘗試過(guò)之后我發(fā)現(xiàn)不行,因?yàn)轫?xiàng)目中使用最多還是@RestController,如果使用webflux的方式,那么很多filter不生效的闸氮。

所以這種方式也不行剪况,但是代碼改得太多了,我只好回退到注釋pom文件依賴的那一步蒲跨。

沒(méi)辦法,只能讀之前對(duì)應(yīng)的代碼邏輯,然后將其轉(zhuǎn)換了译断。

讀取gateway filter的代碼,將其轉(zhuǎn)換成spring filter,直接繼承 org.springframework.web.filter.OncePerRequestFilter 即可,然后將之前的邏輯搬過(guò)來(lái)财骨。

需要注意的是如果是全局filter需要放到公共包里面镐作。

handler也是一樣的,將其轉(zhuǎn)換成filter,需要注意執(zhí)行順序。

這樣,核心代碼改造完畢,可以開(kāi)啟調(diào)試了

遇到的坑

處理上面說(shuō)的webflux的問(wèn)題外,將springcloud變成springboot后,我們之前的配置文件名稱是bootstrap.yml,bootstrap-dev.yml文件,但是改成了springboot后隆箩,配置文件名要改成application.yml,application-env.yml该贾。

不然你會(huì)發(fā)現(xiàn)你啟動(dòng)不了,說(shuō)找不到文件,這個(gè)坑也是自己把自己給坑了捌臊。

然后就是要將gateway的filter轉(zhuǎn)換成spring filter的時(shí)候要注意一定要保證之前的邏輯完全移植過(guò)來(lái)了杨蛋,我就遇到一個(gè)在改造前可以重復(fù)讀取request的流,但是改造后這段代碼報(bào)錯(cuò)了,就是因?yàn)闆](méi)有將這段邏輯移植過(guò)去的問(wèn)題理澎。

改造nacos

前面提到了nacos主要在open-feign的調(diào)用中以及變量注入中使用到了逞力。feign那個(gè)好改,只需要指定url參數(shù)即可,這樣就可以去掉nacos的依賴了。 然后變量注入同樣的我們可以使用Kubernetes的ConfigMap以及Secret來(lái)代替糠爬。

所以我們需要將以前配置到nacos中的變量放到配置文件中,這樣變量可以直接通過(guò)Kubernetes進(jìn)行注入了寇荧。

我們?cè)诟鱾€(gè)環(huán)境中只需要有一份代碼(一個(gè)鏡像),部署的時(shí)候只需要注入的配置不一樣就可以了,這樣就可以保證各個(gè)環(huán)境代碼一致执隧。

比如之前的配置是這樣的

spring:
  redis:
    host: 127.0.0.1
    port: 6379
    database: 0
    password: 123456

改造后配置文件的值為

spring:
  redis:
    host: ${env_redis_host}
    port: ${env_redis_port}
    database: ${env_redis_database}
    password: ${env_redis_password}

而這里的變量是通過(guò)ConfigMap進(jìn)行配置的,到時(shí)候會(huì)注入到容器環(huán)境變量中揩抡,這樣spring就可以從環(huán)境變量中獲取到值了户侥。

部署

之前使用的jenkins方式部署,jenkins也是自己搭建的峦嗤,現(xiàn)在全部遷移到了azure github上,所以這里直接使用azure的pipeline進(jìn)行部署蕊唐。 而我們管理k8s的資源則使用的是helm。

比如我項(xiàng)目中使用helm生成后結(jié)構(gòu)如下

C:.                 
│  .helmignore      
│  Chart.yaml       
│  values-prod.yaml 
│  values-qa.yaml   
│  values-test.yaml 
│  values.yaml      
│                   
├─charts            
├─config            
│  ├─dev            
│  │      config.yaml
│  │      secret.yaml
│  │                
│  ├─prod           
│  │      config.yaml
│  │      secret.yaml
│  │                
│  ├─qa             
│  │      config.yaml
│  │      secret.yaml
│  │                
│  └─test           
│          config.yaml
│          secret.yaml
│                   
└─templates         
        configmap.yaml
        deployment.yaml
        hpa.yaml    
        secret.yaml 
        service.yaml
        _helpers.tpl

這里只需要部署的時(shí)候指定不同的value 文件烁设,就可以實(shí)現(xiàn)同一個(gè)鏡像部署到不同的環(huán)境了替梨。

dev目錄下config.yaml,secret.yaml文件內(nèi)容大致如下:

# config.yaml
env_redis_host: localhost
env_redis_port: 6379
env_redis_database: 1


#secret.yaml

env_redis_password: 123456

在template中configmap.yaml, secret.yaml中主要是如何將文件內(nèi)容轉(zhuǎn)換成對(duì)應(yīng)的yaml

#values.yaml 指定有哪些文件
configOverrides:
  - config/dev/config.yaml
secretOverrides:
  - config/dev/secret.yaml



# configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ include "think-manifesto.fullname" . }}-configmap
  namespace: {{ .Values.nameSpace }}
data:
{{- $files := .Files }}
{{- range  .Values.configOverrides }}
{{- range $key, $value :=  ($files.Get (printf "%s" .) | fromYaml) }}
{{ $key | indent 2 }}: {{ $value | quote }}
{{- end }}
{{- end }}

# secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: {{ include "think-manifesto.fullname" . }}-secret
  namespace: {{ .Values.nameSpace }}
type: Opaque
data:
{{- $files := .Files }}
{{- range  .Values.secretOverrides }}
{{- range $key, $value :=  ($files.Get (printf "%s" .) | fromYaml) }}
{{ $key | indent 2 }}: {{ $value | b64enc }}
{{- end }}
{{- end }}


最后給我deployment.yaml的例子,大家可以參考下

apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ include "think-manifesto.fullname" . }}
  namespace: {{ .Values.nameSpace }}
  labels:
    {{- include "think-manifesto.labels" . | nindent 4 }}
spec:
  replicas: {{ .Values.replicaCount }}
  selector:
    matchLabels:
      {{- include "think-manifesto.selectorLabels" . | nindent 6 }}
  template:
    metadata:
      labels:
        {{- include "think-manifesto.selectorLabels" . | nindent 8 }}
      annotations:
        {{- if .Values.configOverrides}}
        checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }}
        {{- end }}
        {{- if .Values.secretOverrides}}
        checksum/secret: {{ include (print $.Template.BasePath "/secret.yaml") . | sha256sum }}
        {{- end }}
    spec:
      {{- with .Values.imagePullSecrets }}
      imagePullSecrets:
        {{- toYaml . | nindent 8 }}
      {{- end }}
      containers:
        - name: {{ .Chart.Name }}
          image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
          imagePullPolicy: {{ .Values.image.pullPolicy }}
          ports:
            - name: {{ .Values.service.portName }}
              containerPort: {{ .Values.service.port }}
          envFrom:
            {{- if .Values.configOverrides }}
            - configMapRef:
                name: {{ include "think-manifesto.fullname" . }}-configmap
            {{- end }}
            {{- if .Values.secretOverrides }}
            - secretRef:
                name: {{ include "think-manifesto.fullname" . }}-secret
            {{- end }}
          {{- with .Values.livenessProbe }}
          livenessProbe:
            {{- toYaml . | nindent 12 }}
          {{- end }}
          {{- with .Values.readinessProbe }}
          readinessProbe:
            {{- toYaml . | nindent 12 }}
          {{- end }}
          resources:
            {{- toYaml .Values.resources | nindent 12 }}
      {{- with .Values.nodeSelector }}
      nodeSelector:
        {{- toYaml . | nindent 8 }}
      {{- end }}
      {{- with .Values.affinity }}
      affinity:
        {{- toYaml . | nindent 8 }}
      {{- end }}
      {{- with .Values.tolerations }}
      tolerations:
        {{- toYaml . | nindent 8 }}
      {{- end }}

至于values.yaml我就不給出來(lái)了装黑,基本上是其他模板需要什么就寫在上面就好了副瀑。

和Kustomize相比,helm安裝第三方chart很方便,它有自己的倉(cāng)庫(kù)曹体,這里附上我安裝traefik2的命令

# 添加traefiK倉(cāng)庫(kù)
helm repo add traefik   https://traefik.github.io/charts    
#添加國(guó)內(nèi)倉(cāng)庫(kù)       
helm repo add stable http://mirror.azure.cn/kubernetes/charts       
helm repo add aliyun https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts       
helm repo update       
helm repo list

helm install --set deployment.kind=DaemonSet --set namespaceOverride=traefik --set service.enabled=false traefik traefik/traefik

本地驗(yàn)證

當(dāng)你寫好了上面的chart之后,如果你本地沒(méi)有kubernetes環(huán)境(因?yàn)樗赡茉诜?wù)器才存在),而你又想要在本地進(jìn)行驗(yàn)證你寫得是否有問(wèn)題俗扇,那么可以使用下面的命令硝烂。

// 將下面的變量替換成你自己的箕别。 chart-name表示chart的名字,chart-dir表示chart地址
helm template --dry-run --debug --disable-openapi-validation ${chart-name} .\${chart-dir}\

然后如果你想要在k8s環(huán)境中安裝的時(shí)候,而k8s環(huán)境又在遠(yuǎn)端服務(wù)器,那么你可以將chart打包,然后到服務(wù)器中進(jìn)行安裝滞谢,然后也可以在
將chart上傳到服務(wù)器中串稀,然后進(jìn)行安裝(服務(wù)器中要先安裝helm)。

寫到最后

自此,從springcloud遷移到k8s集群總算是完成了狮杨。因?yàn)槭堑谝淮问褂胔elm(以前都用的kustomize),所以在helm這里耗費(fèi)了一些功夫母截,主要是排查錯(cuò)誤方面的,不過(guò)不得不說(shuō)helm的文檔寫得不錯(cuò),很清晰橄教。

再然后就是代碼改造以及一些配置問(wèn)題,因?yàn)檫w移azure,所以上面的關(guān)于它pipeline的一些配置不是很清楚清寇,不過(guò)好在可以直接練習(xí)他們的運(yùn)維,還是幫我們解決了一些問(wèn)題的。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末护蝶,一起剝皮案震驚了整個(gè)濱河市华烟,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌持灰,老刑警劉巖盔夜,帶你破解...
    沈念sama閱讀 219,270評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異堤魁,居然都是意外死亡喂链,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門妥泉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)椭微,“玉大人,你說(shuō)我怎么就攤上這事盲链∮剩” “怎么了检诗?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,630評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)瓢剿。 經(jīng)常有香客問(wèn)我逢慌,道長(zhǎng),這世上最難降的妖魔是什么间狂? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,906評(píng)論 1 295
  • 正文 為了忘掉前任攻泼,我火速辦了婚禮,結(jié)果婚禮上鉴象,老公的妹妹穿的比我還像新娘忙菠。我一直安慰自己,他們只是感情好纺弊,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,928評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布牛欢。 她就那樣靜靜地躺著,像睡著了一般淆游。 火紅的嫁衣襯著肌膚如雪傍睹。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,718評(píng)論 1 305
  • 那天犹菱,我揣著相機(jī)與錄音拾稳,去河邊找鬼。 笑死腊脱,一個(gè)胖子當(dāng)著我的面吹牛访得,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播陕凹,決...
    沈念sama閱讀 40,442評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼悍抑,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了杜耙?” 一聲冷哼從身側(cè)響起搜骡,我...
    開(kāi)封第一講書(shū)人閱讀 39,345評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎泥技,沒(méi)想到半個(gè)月后浆兰,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,802評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡珊豹,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,984評(píng)論 3 337
  • 正文 我和宋清朗相戀三年簸呈,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片店茶。...
    茶點(diǎn)故事閱讀 40,117評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡蜕便,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出贩幻,到底是詐尸還是另有隱情轿腺,我是刑警寧澤两嘴,帶...
    沈念sama閱讀 35,810評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站族壳,受9級(jí)特大地震影響憔辫,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜仿荆,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,462評(píng)論 3 331
  • 文/蒙蒙 一贰您、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧拢操,春花似錦锦亦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,011評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至舔庶,卻和暖如春抛蚁,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背栖茉。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,139評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工篮绿, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人吕漂。 一個(gè)月前我還...
    沈念sama閱讀 48,377評(píng)論 3 373
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像尘应,于是被迫代替她去往敵國(guó)和親惶凝。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,060評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容