使用minikube實(shí)現(xiàn)微服務(wù)的CI/CD

一、概述

最近在研究基于k8s實(shí)現(xiàn)一套devops流程,由于搭建一套k8s集群比較麻煩,所有打算使用minikube在我本地的windows上面實(shí)現(xiàn)整套devops流程,在這里記錄一下整個(gè)實(shí)踐過(guò)程,希望對(duì)需要的同學(xué)提供一些參考,也便于自己以后查閱。

minikube官方地址:https://minikube.sigs.k8s.io/docs/start/

運(yùn)行環(huán)境

windows 10
minikube 1.18.1
kubernetes 1.20.2

二、安裝minikube

minikube是本地的Kubernetes,致力于使Kubernetes易于學(xué)習(xí)和開(kāi)發(fā)。
你需要的只是Docker(或類(lèi)似兼容)容器或虛擬機(jī)環(huán)境,只需一個(gè)命令即可: minikube start即可在本地啟動(dòng)一個(gè)kubernetes集群。

1. 運(yùn)行minikube的條件

說(shuō)明:minikube 提供了跨平臺(tái)搭建k8s的能力,支持mac ,linux ,windows平臺(tái),每一個(gè)平臺(tái)上也支持多種驅(qū)動(dòng)架構(gòu),windows 支持docker,Hyper-V,virtualBox等,由于win10已經(jīng)內(nèi)置了Hyper-V,這里選擇Hyper-V。

2. 在windows中開(kāi)啟Hyper-V

Hyper-V是內(nèi)置于現(xiàn)代Microsoft Windows版本中的本機(jī)虛擬機(jī)管理程序,需要是Windows 10企業(yè)版,專(zhuān)業(yè)版或教育版的64位版本系統(tǒng)才能開(kāi)啟,我這里使用的是windows 10 專(zhuān)業(yè)版系統(tǒng),通過(guò)如下方式開(kāi)啟Hyper-V。

image.png

以管理員身份打開(kāi)PowerShell控制臺(tái),然后運(yùn)行以下命令:

Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V -All

如果Hyper-V先前未處于活動(dòng)狀態(tài),則需要重新啟動(dòng)。我這里已經(jīng)開(kāi)啟了,所以如下圖所示,顯示online ,并且不需要重新。


image.png

3. 下載minikube

下載并運(yùn)行Windows安裝程序

image.png

安裝完成后,搜索cmd并以管理員身份打開(kāi)
image.png

4. 啟動(dòng)minikube

使用如下命令啟動(dòng)minikube會(huì)導(dǎo)致有的鏡像無(wú)法拉取,接著往下面看成功的運(yùn)行命令

minikube start --driver=hyperv --registry-mirror=https://registry.docker-cn.com,https://shraym0v.mirror.aliyuncs.com --embed-certs=true --image-mirror-country=cn --image-repository=registry.cn-hangzhou.aliyuncs.com/google_containers

參數(shù)說(shuō)明
可以通過(guò)minikube start --help查看其它參數(shù)的詳細(xì)說(shuō)明,這里說(shuō)明上面使用的參數(shù)

  • minikube start:?jiǎn)?dòng)一個(gè)本地單節(jié)點(diǎn)kubernetes集群。
  • --driver=hyperv:指定驅(qū)動(dòng)為hyperv,默認(rèn)為自動(dòng)檢測(cè)(virtualbox, vmwarefusion, hyperv, vmware, docker, ssh)中的一個(gè)。
  • --registry-mirror=https://registry.docker-cn.com:使用國(guó)內(nèi)的鏡像地址來(lái)提高拉取鏡像的速度,可以設(shè)置多個(gè)用,分割即可。
  • --embed-certs=true: 如果為true,將在kubeconfig中嵌入證書(shū),默認(rèn)為false,在kubeconfig中將以絕對(duì)路徑的方式讀取證書(shū)文件。
  • --image-mirror-country=cn:需要使用的鏡像的國(guó)家/地區(qū)代碼,留空以使用全球代碼,對(duì)于中國(guó)大陸用戶(hù),請(qǐng)將其設(shè)置為 cn。
  • --image-repository=registry.cn-hangzhou.aliyuncs.com/google_containers:設(shè)置用來(lái)拉取 Kubernetes 集群所需鏡像的倉(cāng)庫(kù),如果無(wú)法訪(fǎng)問(wèn)gcr.io可以設(shè)置為 "auto" 讓minikube 為你自動(dòng)選擇可以訪(fǎng)問(wèn)的鏡像倉(cāng)庫(kù)。對(duì)于中國(guó)大陸用戶(hù)可以設(shè)置registry.cn-hangzhou.aliyuncs.com/google_containers,但是我設(shè)置此參數(shù)導(dǎo)致有的鏡像無(wú)法拉取。

說(shuō)明:通過(guò)上面的命令啟動(dòng)minikube,會(huì)出現(xiàn)有的鏡像無(wú)法拉取的問(wèn)題,也就是說(shuō)registry.cn-hangzhou.aliyuncs.com/google_containers鏡像倉(cāng)庫(kù)很多鏡像不存在,經(jīng)過(guò)不斷的測(cè)試,使用如下命令就可以正常啟動(dòng)并拉取鏡像,所有我們不需要設(shè)置這兩個(gè)參數(shù):--image-mirror-country=cn--image-repository=registry.cn-hangzhou.aliyuncs.com/google_containers

成功啟動(dòng)minikube的命令如下:

minikube start --driver=hyperv --registry-mirror=https://registry.docker-cn.com,https://shraym0v.mirror.aliyuncs.com --embed-certs=true

5. 驗(yàn)證minikube

使用如下命令查看minikube的狀態(tài)

C:\WINDOWS\system32>minikube status
minikube
type: Control Plane
host: Running
kubelet: Running
apiserver: Running
kubeconfig: Configured
timeToStop: Nonexistent
# 這里會(huì)自動(dòng)下載kubectl工具
C:\WINDOWS\system32>minikube kubectl get node
NAME       STATUS   ROLES                  AGE   VERSION
minikube   Ready    control-plane,master   11m   v1.20.2

部署一個(gè)nginx,快速體驗(yàn)minikube

C:\WINDOWS\system32>kubectl create deployment nginx --image=nginx
deployment.apps/nginx created

C:\WINDOWS\system32>kubectl get pod
NAME                     READY   STATUS    RESTARTS   AGE
nginx-6799fc88d8-z7xzh   1/1     Running   0          33s

C:\WINDOWS\system32>kubectl expose deployment nginx --type=NodePort --port=80
service/nginx exposed

C:\WINDOWS\system32>minikube service nginx
|-----------|-------|-------------|----------------------------|
| NAMESPACE | NAME  | TARGET PORT |            URL             |
|-----------|-------|-------------|----------------------------|
| default   | nginx |          80 | http://172.23.130.60:31593 |
|-----------|-------|-------------|----------------------------|
* 正通過(guò)默認(rèn)瀏覽器打開(kāi)服務(wù) default/nginx...

C:\WINDOWS\system32>

會(huì)自動(dòng)打開(kāi)默認(rèn)瀏覽器,如下圖所示:


image.png

使用如下命令啟動(dòng)k8s的dashboard

C:\WINDOWS\system32>minikube dashboard
* 正在開(kāi)啟 dashboard ...
  - Using image kubernetesui/dashboard:v2.1.0
  - Using image kubernetesui/metrics-scraper:v1.0.4
* 正在驗(yàn)證 dashboard 運(yùn)行情況 ...
* Launching proxy ...
* 正在驗(yàn)證 proxy 運(yùn)行狀況 ...
* Opening http://127.0.0.1:61589/api/v1/namespaces/kubernetes-dashboard/services/http:kubernetes-dashboard:/proxy/ in your default browser...

如下圖所示:


image.png

三、安裝jenkins

我這里使用yaml的方式部署jenkins,并且創(chuàng)建pv和pvc來(lái)持久化jenkins的數(shù)據(jù),所有創(chuàng)建三個(gè)文件:

  • jenkins-pvc.yaml:設(shè)置jenkins數(shù)據(jù)持久化方式。
  • jenkins-rbac.yaml:設(shè)置jenkins用戶(hù)訪(fǎng)問(wèn)權(quán)限。
  • jenkins-deploy.yaml:創(chuàng)建jenkins的deployment 和 service。
    jenkins-pvc.yaml文件內(nèi)容如下:
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: jenkins-pvc
  namespace: devops
spec:
  accessModes:
  - ReadWriteMany
  # 如果集群中有一個(gè)默認(rèn)的storageClass能滿(mǎn)足需求,這里可以不用配置storageClass
  storageClassName: standard
  resources:
    requests:
      storage: 5Gi

說(shuō)明:因?yàn)槭褂胢inikube創(chuàng)建的k8s集群默認(rèn)已經(jīng)創(chuàng)建了一個(gè)基于hostpathstorageClass,通過(guò)如下命令查看

C:\windows\system32>kubectl get sc
NAME                 PROVISIONER                RECLAIMPOLICY   VOLUMEBINDINGMODE   >ALLOWVOLUMEEXPANSION   AGE
standard (default)   k8s.io/minikube-hostpath   Delete          Immediate           false                  98m

storageClass會(huì)自動(dòng)創(chuàng)建pv,并將pv和pvc進(jìn)行綁定,所以我們無(wú)需自己創(chuàng)建pv。

jenkins-rbac.yaml文件內(nèi)容如下:

apiVersion: v1
kind: ServiceAccount
metadata:
  name: jenkins-sa
  namespace: devops

---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: jenkins-cr
rules:
  - apiGroups: ["extensions", "apps"]
    resources: ["deployments"]
    verbs: ["create", "delete", "get", "list", "watch", "patch", "update"]
  - apiGroups: [""]
    resources: ["services"]
    verbs: ["create", "delete", "get", "list", "watch", "patch", "update"]
  - apiGroups: [""]
    resources: ["pods"]
    verbs: ["create","delete","get","list","patch","update","watch"]
  - apiGroups: [""]
    resources: ["pods/exec"]
    verbs: ["create","delete","get","list","patch","update","watch"]
  - apiGroups: [""]
    resources: ["pods/log"]
    verbs: ["get","list","watch"]
  - apiGroups: [""]
    resources: ["secrets"]
    verbs: ["get"]

---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: jenkins-crd
roleRef:
  kind: ClusterRole
  name: jenkins-cr
  apiGroup: rbac.authorization.k8s.io
subjects:
- kind: ServiceAccount
  name: jenkins-sa
  namespace: devops

jenkins-deploy.yaml文件內(nèi)容如下:

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: jenkins
  namespace: devops 
spec:
  replicas: 1
  selector:
    matchLabels:
      app: jenkins
  template:
    metadata:
      labels:
        app: jenkins
    spec:
      terminationGracePeriodSeconds: 10
      serviceAccount: jenkins-sa
      containers:
      - name: jenkins
        image: jenkins/jenkins:latest
        imagePullPolicy: IfNotPresent
        env:
        - name: JAVA_OPTS
          value: -Duser.timezone=Asia/Shanghai
        ports:
        - containerPort: 8080
          name: web
          protocol: TCP
        - containerPort: 50000
          name: agent
          protocol: TCP
        resources:
          limits:
            cpu: 1000m
            memory: 1Gi
          requests:
            cpu: 500m
            memory: 512Mi
        livenessProbe:
          httpGet:
            path: /login
            port: 8080
          initialDelaySeconds: 60
          timeoutSeconds: 5
          failureThreshold: 12
        readinessProbe:
          httpGet:
            path: /login
            port: 8080
          initialDelaySeconds: 60
          timeoutSeconds: 5
          failureThreshold: 12
        volumeMounts:
          - name: jenkinshome
            mountPath: /var/jenkins_home
      volumes:
        - name: jenkinshome
          persistentVolumeClaim:
            claimName: jenkins-pvc

---
apiVersion: v1
kind: Service
metadata:
  name: jenkins
  namespace: devops 
  labels:
    app: jenkins
spec:
  selector:
    app: jenkins
  type: NodePort
  ports:
  - name: web
    port: 8080
    targetPort: web
    
    
---
apiVersion: v1
kind: Service
metadata:
  name: jenkins-agent
  namespace: devops 
  labels:
    app: jenkins
spec:
  selector:
    app: jenkins
  type: ClusterIP
  ports:
  - name: agent
    port: 50000
    targetPort: agent

使用下面的命令部署jenkins

  1. 創(chuàng)建devops命名空間
C:\WINDOWS\system32>kubectl create namespace devops
namespace/devops created
  1. 執(zhí)行下面的命令啟動(dòng)jenkins
kubectl apply -f jenkins-pvc.yaml
kubectl apply -f jenkins-rbac.yaml
kubectl apply -f jenkins-deploy.yaml
  1. 使用minikube service命令提供瀏覽器訪(fǎng)問(wèn)地址
C:\WINDOWS\system32>minikube service jenkins -n devops
|-----------|---------|-------------|----------------------------|
| NAMESPACE |  NAME   | TARGET PORT |            URL             |
|-----------|---------|-------------|----------------------------|
| devops    | jenkins | web/8080    | http://172.23.130.60:30002 |
|-----------|---------|-------------|----------------------------|
* 正通過(guò)默認(rèn)瀏覽器打開(kāi)服務(wù) devops/jenkins...
image.png
  1. 使用如下命令查看登錄jenkins的初始密碼
C:\WINDOWS\system32>kubectl get pod -n devops
NAME                       READY   STATUS    RESTARTS   AGE
jenkins-6bb66dcf88-2c4tv   1/1     Running   0          9m59s

C:\WINDOWS\system32>kubectl logs -f jenkins-6bb66dcf88-2c4tv -n devops

查看jenkins初始密碼如下圖:


image.png

選擇自定義插件安裝,因?yàn)榛厝ス倬W(wǎng)下載插件,下載比較慢,而且很多插件我們不需要


image.png

取消推薦插件的選擇
image.png

創(chuàng)建一個(gè)管理員賬號(hào)


image.png

開(kāi)始使用jenkins
image.png

Jenkins下載插件設(shè)置國(guó)內(nèi)源

image.png

安裝如下插件


image.png

四、在jenkins中配置k8s實(shí)現(xiàn)CI/CD

1. k8s相關(guān)配置

  • 選擇 [節(jié)點(diǎn)管理] -> [Configure Clouds]


    image.png
  • 安裝了kubernetes插件就可看到下圖所示,添加一個(gè)kubernetes的cloud


    image.png
  • 配置連接k8s的api server


    image.png
  • 創(chuàng)建pod template


    image.png
  • 添加第一個(gè)容器 jnlp(jnlp-slave)


    image.png

    image.png
  • 添加第二個(gè)容器 docker(因?yàn)橐趐ipeline中構(gòu)建鏡像,需要使用docker客戶(hù)端,此鏡像提供了docker客戶(hù)端)


    image.png
  • 添加第三個(gè)容器 maven (這里使用的鏡像為:registry.cn-beijing.aliyuncs.com/acs-sample/jenkins-slave-maven:3.3.9-jdk-8-alpine, 也可以使用自定義的maven鏡像)


    image.png
  • pod 模板的數(shù)據(jù)卷的設(shè)置,如下圖所示:
    創(chuàng)建docker推送鏡像到私用倉(cāng)庫(kù)的secret
    命令如下:kubectl create secret generic my-secret --from-file=/root/.docker/config.json

注意: 這里不是 kubectl create secret docker-registry my-secret --docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL
這里遇到一個(gè)問(wèn)題,docker 無(wú)法推送鏡像,報(bào)錯(cuò)顯示docker沒(méi)有登錄私有倉(cāng)庫(kù),查詢(xún)?cè)虬l(fā)現(xiàn)因?yàn)槲沂褂胐ocker-registry創(chuàng)建了my-secret,當(dāng)我改為generic就可以了,詳細(xì)信息可以查看k8s的secret說(shuō)明文檔。

image.png
  • [Manage Credentials] -> [jenkins] -> [全局憑據(jù)] -> [添加憑據(jù)]
    配置訪(fǎng)問(wèn)k8s的kubeconfig,在pipeline中使用kubernetesDeploy的時(shí)候會(huì)使用到

    image.png

  • [Manage Credentials] -> [jenkins] -> [全局憑據(jù)] -> [添加憑據(jù)]
    設(shè)置登錄私有鏡像倉(cāng)庫(kù)的用戶(hù)名和密碼


    image.png

五、使用jenkins CI/CD demo演示

  • 新建一個(gè)任務(wù) devops-demo


    image.png
  • devops-demo任務(wù)配置如下:
    1、指定docker私有倉(cāng)庫(kù)地址


    image.png

    2、指定項(xiàng)目名稱(chēng)


    image.png

    3、指定要部署的命名空間
    image.png

    4、選擇構(gòu)建的分支
    image.png

5、任務(wù)流水線(xiàn)配置


image.png

說(shuō)明: 這里使用的倉(cāng)庫(kù)代碼示例地址如下:https://gitee.com/peterwd/devops-demo.git
在倉(cāng)庫(kù)中需要添加三個(gè)文件才能實(shí)現(xiàn)此devops流程:Jenkinsfile、Dockerfile、deployment.yaml
文件的內(nèi)容可以點(diǎn)擊到倉(cāng)庫(kù)中查看。

  • 保存配置并構(gòu)建如下圖所示


    image.png
  • 構(gòu)建成功的效果如下


    image.png

這里打包階段用時(shí)比較長(zhǎng),那是因?yàn)槊看螛?gòu)建都需要下載依賴(lài),因?yàn)閟lave運(yùn)行完成就會(huì)被銷(xiāo)毀,默認(rèn)下載的依賴(lài)就在slave容器中,會(huì)隨著slave容器的銷(xiāo)毀而消失,所以我們應(yīng)該把下載的依賴(lài)持久化下來(lái),下面介紹如何實(shí)現(xiàn):
1、將下載的依賴(lài)持久化到宿主機(jī),使用如下方式配置:
在maven容器中,默認(rèn)將依賴(lài)包放在/root/.m2/repository目錄下面,所以我們可以將宿主機(jī)的指定目錄掛載到此目錄中:

image.png

再次構(gòu)建可以通過(guò)如下方式登錄到宿主機(jī)查看下載的依賴(lài)已經(jīng)持久化到宿主機(jī)對(duì)應(yīng)的目錄中:

# 登錄到minikube節(jié)點(diǎn)中
C:\windows\system32>minikube ssh
                         _             _
            _         _ ( )           ( )
  ___ ___  (_)  ___  (_)| |/')  _   _ | |_      __
/' _ ` _ `\| |/' _ `\| || , <  ( ) ( )| '_`\  /'__`\
| ( ) ( ) || || ( ) || || |\`\ | (_) || |_) )(  ___/
(_) (_) (_)(_)(_) (_)(_)(_) (_)`\___/'(_,__/'`\____)

$ cd /tmp/maven/repository/
$ ls -al
total 0
drwxr-xr-x 16 root root 320 Mar 15 10:25 .
drwxr-xr-x  3 root root  60 Mar 15 10:21 ..
drwxr-xr-x  3 root root  60 Mar 15 10:24 backport-util-concurrent
drwxr-xr-x  3 root root  60 Mar 15 10:22 ch
drwxr-xr-x  3 root root  60 Mar 15 10:23 classworlds
drwxr-xr-x  5 root root 100 Mar 15 10:24 com
drwxr-xr-x  3 root root  60 Mar 15 10:23 commons-cli
drwxr-xr-x  3 root root  60 Mar 15 10:25 commons-codec
drwxr-xr-x  3 root root  60 Mar 15 10:25 commons-lang
drwxr-xr-x  4 root root  80 Mar 15 10:25 commons-logging
drwxr-xr-x  8 root root 160 Mar 15 10:22 io
drwxr-xr-x  3 root root  60 Mar 15 10:22 jakarta
drwxr-xr-x  3 root root  60 Mar 15 10:23 junit
drwxr-xr-x  3 root root  60 Mar 15 10:24 log4j
drwxr-xr-x  3 root root  60 Mar 15 10:25 net
drwxr-xr-x 13 root root 260 Mar 15 10:23 org
$

2、使用pvc 持久化mave的依賴(lài)包,進(jìn)行如下圖所示配置:


image.png
  • 持久化maven依賴(lài)包,再次構(gòu)建耗時(shí)對(duì)比如下:


    image.png

遇到的問(wèn)題

1. minikube啟動(dòng)失敗

* 正在 Docker 20.10.3 中準(zhǔn)備 Kubernetes v1.20.2…| E0313 13:19:52.379165   33644 start.go:99] Unable to get host IP: No virtual switch found
X Exiting due to GUEST_START: Failed to setup kubeconfig: No virtual switch found

如下圖所示:

image.png

出現(xiàn)錯(cuò)誤的原因
第一次由于電腦內(nèi)存不足導(dǎo)致安裝失敗,再次啟動(dòng)minikube時(shí)報(bào)出此錯(cuò)誤。
解決方式
執(zhí)行如下命令,刪除所有minikube集群,再重新啟動(dòng)即可恢復(fù)正常:

minikube delete --all

2. jenkins插件下載失敗

部分插件由于缺少依賴(lài)無(wú)法加載。要恢復(fù)這些插件提供的功能,需要修復(fù)這些問(wèn)題并重啟 Jenkins。
Dependency errors:
SSH Credentials Plugin (1.18.2)
Jenkins (2.282) or higher required
由于一個(gè)或者多個(gè)上面的錯(cuò)誤導(dǎo)致這些插件無(wú)法加載。修復(fù)后插件將會(huì)再次加載。

image.png

解決方式
升級(jí)jenkins版本為提示的版本,可以直接修改jenkins-deploy.yaml文件中的image: jenkins/jenkins:latestimage: jenkins/jenkins:2.283

參考文章
minikube快速搭建k8s
kubernetes中部署Jenkins并簡(jiǎn)單使用
Jenkins 和 Kubernetes -云上的神秘代理
k8s學(xué)習(xí)筆記之StorageClass+NFS

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

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

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