記一次aspnetcore發(fā)布部署流程初次使用k8s
主題:
aspnetcorewebapi項(xiàng)目,提交到gitlab,通過(guò)jenkins(gitlab的ci/cd)編譯、發(fā)布、推送到k8s。
關(guān)于gitlab、jenkins、k8s安裝,都是使用docker啟動(dòng)服務(wù)。
首先新建一個(gè)項(xiàng)目,為了方便瀏覽就把swaggerr非開(kāi)發(fā)環(huán)境不展示去掉


下面就是需要準(zhǔn)備Dockerfile和k8s.yaml文件,這里不應(yīng)該用net5,過(guò)時(shí)了。
FROM mcr.microsoft.com/dotnet/aspnet:5.0-buster-slim AS base COPY . /app WORKDIR /app EXPOSE 5000/tcp ENV ASPNETCORE_URLS http://*:5000/ ENV TZ=Asia/Shanghai # Work around for broken dotnet restore ADD http://ftp.us.debian.org/debian/pool/main/c/ca-certificates/ca-certificates_20210119_all.deb . RUN dpkg -i ca-certificates_20210119_all.deb # soft link RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone RUN ln -s /lib/x86_64-linux-gnu/libdl-2.24.so /lib/x86_64-linux-gnu/libdl.so # install System.Drawing native dependencies RUN apt-get update \ && apt-get install -y --allow-unauthenticated \ ca-certificates \ && update-ca-certificates \ libgdiplus \ && rm -rf /var/lib/apt/lists/* ENTRYPOINT ["dotnet", "autopubtest.dll"]
apiVersion: apps/v1 kind: Deployment metadata: name: {deployName} labels: app: {deployName} namespace: default spec: replicas: 2 selector: matchLabels: app: {deployName} template: metadata: labels: app: {deployName} spec: nodeSelector: group: web containers: - name: {containerName} image: {imageRegistry}/{imageName}:{imageTag} volumeMounts: - name: config-volume mountPath: /app/appsettings.Production.json subPath: appsettings.Production.json env: - name: ASPNETCORE_ENVIRONMENT value: Production ports: - containerPort: 5000 volumes: - name: config-volume configMap: name: autopubtest-config imagePullSecrets: - name: docker-secret --- kind: Service apiVersion: v1 metadata: name: {serviceName} labels: app: {serviceName} namespace: default spec: selector: app: {deployName} ports: - name: {serviceName} port: 5000 protocol: TCP targetPort: 5000
這里需要注意的是configMap的name是我們需要再K8S里面建的appsettings.環(huán)境.json文件
configMap:
name: autopubtest-config
一切準(zhǔn)備就緒,本地需要有docker環(huán)境,就能驗(yàn)證dockerfile是否有報(bào)錯(cuò),我本地是dockerdesktop。
下面就先把代碼提交到gitlab,我是用develop自建分支,而且我用的是http

這里gitlab
v17.1.1
有一個(gè)問(wèn)題就是默認(rèn)會(huì)把容器的id當(dāng)成請(qǐng)求的ip地址,通過(guò)git 的git或者h(yuǎn)ttp拉取代碼這里都會(huì)有問(wèn)題,進(jìn)入gitlab的容器內(nèi)部找到 /etc/gitlab/gitlab.rb找到external_url注釋掉的一行,改下你實(shí)際的地址和端口就行。

這里稍微提一下gitlab的ci/cd,本篇主要是jenkins。
gitlab安裝完默認(rèn)密碼存放在 /etc/gitlab/initial_root_password ,默認(rèn)用戶root
networks:指定唯一,在服務(wù)器中新建一個(gè)networks,方便一個(gè)網(wǎng)段通信,如果是分開(kāi)的服務(wù)器就是用ip或者其他。
register runner的時(shí)候手敲,ip指定gitlab容器的內(nèi)網(wǎng)ip,查看命令 docker inspect docker容器id,類似這樣的,下面提示就是成功注冊(cè)一個(gè)runner
Registering runner... succeeded runner=
gitlab-runner register \ --url http://gitlab的docker的ip \ --registration-token gitlab runners中的token \ --executor docker \ --description "My Docker Runner" \ --docker-image "alpine:latest"
這里是安裝gitlab和gitlab-runner的docker-compose.yml
version: '3.3' services: gitlab: image: gitlab/gitlab-ce:latest container_name: gitlab ports: - "80:80" networks: - my-network gitlab-runner: image: gitlab/gitlab-runner:latest container_name: gitlab-runner restart: always volumes: - /var/run/docker.sock:/var/run/docker.sock networks: - my-network networks: my-network: driver: bridge
只要在項(xiàng)目中新增.gitlab-ci.yml,再把類似jenkins的shell操作放到文件中就可以了。這里有一個(gè)測(cè)試的文件,tags很重要,注冊(cè)runner的時(shí)候指定需要的,再在文件中配置了,就會(huì)按照流程。
stages: # List of stages for jobs, and their order of execution - build - test - deploy build-job: # This job runs in the build stage, which runs first. stage: build tags: # Add the tags here - docker - linux script: - echo "Compiling the code..." - echo "Compile complete." unit-test-job: # This job runs in the test stage. stage: test # It only starts when the job in the build stage completes successfully. tags: # Add the tags here - docker - linux script: - echo "Running unit tests... This will take about 60 seconds." - sleep 60 - echo "Code coverage is 90%" lint-test-job: # This job also runs in the test stage. stage: test # It can run at the same time as unit-test-job (in parallel). tags: # Add the tags here - docker - linux - fast script: - echo "Linting code... This will take about 10 seconds." - sleep 10 - echo "No lint issues found." deploy-job: # This job runs in the deploy stage. stage: deploy # It only runs when *both* jobs in the test stage complete successfully. tags: # Add the tags here - docker - linux - fast environment: production script: - echo "Deploying application..." - echo "Application successfully deployed."
上面僅僅只是一個(gè)測(cè)試完整流程文件,不涉及docker打包操作,需要docker打包的話runner就需要安裝,安裝模式有幾種,自行查資料。

下面介紹jenkins的操作



這里提一提,通過(guò)git拉取代碼,需要在jenkins的容器內(nèi)部生成.ssh的公鑰私鑰,公鑰添加到gitlab的ssh中,私鑰就放到j(luò)enkins的全局變量中,Credentials就可以選擇你的驗(yàn)證方式了。
下面的選擇會(huì)影響你拉取代碼,第一個(gè)設(shè)置你有可能需要在jenkins容器內(nèi)部拉取一次代碼,最后一個(gè)設(shè)置可以通過(guò)http拉。


下面繼續(xù):


這里我有三個(gè)步驟,編譯,發(fā)布,K8S拉取鏡像
第一部分 #!/bin/bash echo "========== 當(dāng)前 Branch: $GIT_BRANCH ==========" echo "========== Commit Hash: $GIT_COMMIT ==========" cd $WORKSPACE/src/autopubtest/ dotnet restore if [ -d $WORKSPACE/publish ]; then rm -rf $WORKSPACE/publish fi dotnet publish -c Release -o $WORKSPACE/publish --no-restore if [ $? -ne 0 ]; then echo "!!!!!!!!!!編譯失敗!!!!!!!!!!" exit 1 else echo "<<<<<<<<<<編譯成功>>>>>>>>>>" fi 第二部分 #!/bin/bash ob=`echo $jobName|tr 'A-Z' 'a-z'|cut -d '.' -f 2` imageName="autopubtest-api" #imageTag=$TagName imageTag=`echo "$GIT_COMMIT" | cut -b1-8` pushRegistry=鏡像倉(cāng)庫(kù)/項(xiàng)目名 echo "========== 開(kāi)始構(gòu)建鏡像 ==========" docker login -u 倉(cāng)庫(kù)賬號(hào) -p 倉(cāng)庫(kù)密碼 $pushRegistry cd $WORKSPACE/publish docker build --rm -t $imageName:$imageTag -f $WORKSPACE/docker/Dockerfile . if [ $? -ne 0 ]; then echo "!!!!!!!!!!鏡像構(gòu)建失敗!!!!!!!!!!" exit 1 else echo "<<<<<<<<<<鏡像構(gòu)建成功 $imageName:$imageTag>>>>>>>>>>" fi docker tag $imageName:$imageTag $pushRegistry/$imageName:$imageTag docker push $pushRegistry/$imageName:$imageTag if [ $? -ne 0 ]; then echo "!!!!!!!!!!鏡像發(fā)布失敗!!!!!!!!!!" exit 1 else echo "<<<<<<<<<<鏡像發(fā)布成功 $imageName:$imageTag>>>>>>>>>>" fi docker rmi $imageName:$imageTag docker rmi $pushRegistry/$imageName:$imageTag 第三部分 projectName="autopubtest-api" #imageTag=$TagName imageTag=`echo "$GIT_COMMIT" | cut -b1-8` deployName=$projectName serviceName=$projectName containerName=$projectName imageName=$projectName git_message=`git log --format=format:%s -1 ${GIT_COMMIT}` pullRegistry=倉(cāng)庫(kù)地址/項(xiàng)目名 cat $WORKSPACE/docker/k8s.yaml | sed 's|'extensions/v1beta1'|'apps/v1'|g; s|{imageRegistry}|'$pullRegistry'|g; s|{imageName}|'$imageName'|g; s|{imageTag}|'$imageTag'|g; s|{deployName}|'$deployName'|g; s|{serviceName}|'$serviceName'|g; s|{containerName}|'$containerName'|g' > $WORKSPACE/docker/k8s.value sed -i '/^---/,$d' $WORKSPACE/docker/k8s.value kubectl apply -f $WORKSPACE/docker/k8s.value if [ $? -ne 0 ]; then echo "!!!!!!!!!!更新失敗,Deployment $deployName 可能不存在,嘗試創(chuàng)建該Deployment!!!!!!!!!!" kubectl create -f $WORKSPACE/docker/k8s.value fi
構(gòu)建的日志就略過(guò),這里使用的是harbor倉(cāng)庫(kù),注需要注意,docker login需要登陸harbor的倉(cāng)庫(kù),在harbor主機(jī)host通過(guò)ip地址映射一個(gè)隨意取名的域名,不要用ip,否則觸發(fā)https安全檢查。

jenkins的第三步,會(huì)觸發(fā)k8s去pull倉(cāng)庫(kù)鏡像。關(guān)于jenkins和k8s的關(guān)聯(lián)就是把k8s主機(jī)的config文件拷貝到j(luò)enkins的 ./var/jenkins_home/root/.kube/config
當(dāng)K8S拉取鏡像后,服務(wù)正常啟動(dòng)。

配置字典里新建autopubtest的appsettings.Production.json文件,該名稱需要與k8s。yaml的對(duì)應(yīng)起來(lái)autopubtest-config

新建下面的服務(wù)


下面就能正常使用接口了



浙公網(wǎng)安備 33010602011771號(hào)