記一次aspnetcore釋出部署流程初次使用k8s

星仔007發表於2024-07-05

主題:

aspnetcorewebapi專案,提交到gitlab,透過jenkins(gitlab的ci/cd)編譯、釋出、推送到k8s。

關於gitlab、jenkins、k8s安裝,都是使用docker啟動服務。

首先新建一個專案,為了方便瀏覽就把swaggerr非開發環境不展示去掉

下面就是需要準備Dockerfile和k8s.yaml檔案,這裡不應該用net5,過時了。

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.環境.json檔案

  configMap:
          name: autopubtest-config

  

一切準備就緒,本地需要有docker環境,就能驗證dockerfile是否有報錯,我本地是dockerdesktop。

下面就先把程式碼提交到gitlab,我是用develop自建分支,而且我用的是http

這裡gitlab

v17.1.1

有一個問題就是預設會把容器的id當成請求的ip地址,透過git 的git或者http拉取程式碼這裡都會有問題,進入gitlab的容器內部找到 /etc/gitlab/gitlab.rb找到external_url註釋掉的一行,改下你實際的地址和埠就行。

這裡稍微提一下gitlab的ci/cd,本篇主要是jenkins。

gitlab安裝完預設密碼存放在 /etc/gitlab/initial_root_password ,預設使用者root

networks:指定唯一,在伺服器中新建一個networks,方便一個網段通訊,如果是分開的伺服器就是用ip或者其他。
register runner的時候手敲,ip指定gitlab容器的內網ip,檢視命令 docker inspect docker容器id,類似這樣的,下面提示就是成功註冊一個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

只要在專案中新增.gitlab-ci.yml,再把類似jenkins的shell操作放到檔案中就可以了。這裡有一個測試的檔案,tags很重要,註冊runner的時候指定需要的,再在檔案中配置了,就會按照流程。

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."

上面僅僅只是一個測試完整流程檔案,不涉及docker打包操作,需要docker打包的話runner就需要安裝,安裝模式有幾種,自行查資料。

下面介紹jenkins的操作

這裡提一提,透過git拉取程式碼,需要在jenkins的容器內部生成.ssh的公鑰私鑰,公鑰新增到gitlab的ssh中,私鑰就放到jenkins的全域性變數中,Credentials就可以選擇你的驗證方式了。

下面的選擇會影響你拉取程式碼,第一個設定你有可能需要在jenkins容器內部拉取一次程式碼,最後一個設定可以透過http拉。

下面繼續:

這裡我有三個步驟,編譯,釋出,K8S拉取映象

第一部分

#!/bin/bash

echo "==========  當前 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=映象倉庫/專案名
    
echo "==========  開始構建映象 =========="

docker login -u 倉庫賬號 -p 倉庫密碼 $pushRegistry
cd $WORKSPACE/publish
docker build --rm -t $imageName:$imageTag -f $WORKSPACE/docker/Dockerfile .

if [ $? -ne 0 ]; then
  echo "!!!!!!!!!!映象構建失敗!!!!!!!!!!"
  exit 1
else
  echo "<<<<<<<<<<映象構建成功 $imageName:$imageTag>>>>>>>>>>"
fi

                                        
docker tag $imageName:$imageTag $pushRegistry/$imageName:$imageTag
docker push $pushRegistry/$imageName:$imageTag

if [ $? -ne 0 ]; then
  echo "!!!!!!!!!!映象釋出失敗!!!!!!!!!!"
  exit 1
else
  echo "<<<<<<<<<<映象釋出成功 $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=倉庫地址/專案名

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 可能不存在,嘗試建立該Deployment!!!!!!!!!!"
  kubectl      create -f $WORKSPACE/docker/k8s.value 
fi

構建的日誌就略過,這裡使用的是harbor倉庫,注需要注意,docker login需要登陸harbor的倉庫,在harbor主機host透過ip地址對映一個隨意取名的域名,不要用ip,否則觸發https安全檢查。

jenkins的第三步,會觸發k8s去pull倉庫映象。關於jenkins和k8s的關聯就是把k8s主機的config檔案複製到jenkins的 ./var/jenkins_home/root/.kube/config

當K8S拉取映象後,服務正常啟動。

配置字典裡新建autopubtest的appsettings.Production.json檔案,該名稱需要與k8s。yaml的對應起來autopubtest-config

新建下面的服務

下面就能正常使用介面了

相關文章