基于Docker托管Azure DevOps代理

Azure DevOps非常好用,但是為代理準備單獨的服務器經常會顯得性價比不高:配置低了,前端構建時會教會你做人,配置太高又有點浪費資源,代理數量少了各團隊構建要打架。對于既想享受DevOps的美妙之處但是資源捉襟見肘的小公司,真是一件比較頭痛的事情。那么有沒有更具備性價比的方案呢?那自然是有的,那就是基于Docker進行自托管。

這里不建議大家丟k8s集群里面去,一是會搶資源,二是k8s容器運行時不推薦大家使用docker,三是不安全。那么現在我們就可以準備一臺好點的服務器,來基于Docker來托管自有的Azure DevOps代理。

編寫Dockerfile

廢話不多,建議大家直接抄代碼吧:

FROM ubuntu:20.04
RUN DEBIAN_FRONTEND=noninteractive apt-get update
RUN DEBIAN_FRONTEND=noninteractive apt-get upgrade -yRUN DEBIAN_FRONTEND=noninteractive apt-get install -y -qq --no-install-recommends \apt-transport-https \apt-utils \ca-certificates \curl \git \iputils-ping \jq \lsb-release \software-properties-common \gss-ntlmsspRUN curl -sL https://aka.ms/InstallAzureCLIDeb | bash# Can be 'linux-x64', 'linux-arm64', 'linux-arm', 'rhel.6-x64'.
ENV TARGETARCH=linux-x64WORKDIR /azp
COPY ./start.sh .
COPY ./vsts-agent-linux-x64-2.181.2.tar.gz .
RUN chmod +x start.shENTRYPOINT [ "./start.sh" ]

如果對Dockerfile不理解,可以參考筆者之前的教程、博客和書籍《Docker+Kubernetes應用開發與快速上云》來解決問題以及查看日志。這里不建議大家使用官方教程,基本上走不通還問題頗多。

值得注意的是,上面涉及到了兩個文件:

  1. start.sh

  2. vsts-agent-linux-x64-2.181.2.tar.gz(從Azure DevOps管理界面下載)

start.sh腳本內容參考如下:

#!/bin/bash
set -eif [ -z "$AZP_URL" ]; thenecho 1>&2 "error: missing AZP_URL environment variable"exit 1
fiif [ -z "$AZP_TOKEN_FILE" ]; thenif [ -z "$AZP_TOKEN" ]; thenecho 1>&2 "error: missing AZP_TOKEN environment variable"exit 1fiAZP_TOKEN_FILE=/azp/.tokenecho -n $AZP_TOKEN > "$AZP_TOKEN_FILE"
fiunset AZP_TOKENif [ -n "$AZP_WORK" ]; thenmkdir -p "$AZP_WORK"
fiexport AGENT_ALLOW_RUNASROOT="1"cleanup() {if [ -e config.sh ]; thenprint_header "Cleanup. Removing Azure Pipelines agent..."# If the agent has some running jobs, the configuration removal process will fail.# So, give it some time to finish the job.while true; do./config.sh remove --unattended --auth negotiate --userName build --password $(cat "$AZP_TOKEN_FILE") && breakecho "Retrying in 30 seconds..."sleep 30donefi
}print_header() {lightcyan='\033[1;36m'nocolor='\033[0m'echo -e "${lightcyan}$1${nocolor}"
}# Let the agent ignore the token env variables
export VSO_AGENT_IGNORE=AZP_TOKEN,AZP_TOKEN_FILEprint_header "1. Determining matching Azure Pipelines agent..."print_header "url=$AZP_URL/_apis/distributedtask/packages/agent?platform=$TARGETARCH&top=1"# AZP_AGENT_PACKAGES=$(curl -LsS \
#     -u user:$(cat "$AZP_TOKEN_FILE") \
#     -H 'Accept:application/json;' \
#     "$AZP_URL/_apis/distributedtask/packages/agent?platform=$TARGETARCH&top=1")AZP_AGENT_PACKAGES=$(curl -LsS \--ntlm \-u build:$(cat "$AZP_TOKEN_FILE") \-H 'Accept:application/json;' \"$AZP_URL/_apis/distributedtask/packages/agent?platform=$TARGETARCH&top=1")print_header "$AZP_AGENT_PACKAGES"AZP_AGENT_PACKAGE_LATEST_URL=$(echo "$AZP_AGENT_PACKAGES" | jq -r '.value[0].downloadUrl')# print_header "1.2 AZP_AGENT_PACKAGE_LATEST_URL=$AZP_AGENT_PACKAGE_LATEST_URL..."if [ -z "$AZP_AGENT_PACKAGE_LATEST_URL" -o "$AZP_AGENT_PACKAGE_LATEST_URL" == "null" ]; thenecho 1>&2 "error: could not determine a matching Azure Pipelines agent"echo 1>&2 "check that account '$AZP_URL' is correct and the token is valid for that account"exit 1
fiprint_header "2. extracting Azure Pipelines agent..."tar zxf ./vsts-agent-linux-x64-2.181.2.tar.gz & wait $!
#curl -LsS $AZP_AGENT_PACKAGE_LATEST_URL | tar -xz & wait $!source ./env.shprint_header "3. Configuring Azure Pipelines agent..."./config.sh --unattended \--agent "${AZP_AGENT_NAME:-$(hostname)}" \--url "$AZP_URL" \--auth negotiate \--userName build \--password $(cat "$AZP_TOKEN_FILE") \--pool "${AZP_POOL:-Default}" \--work "${AZP_WORK:-_work}" \--replace \--acceptTeeEula & wait $!print_header "4. Running Azure Pipelines agent..."trap 'cleanup; exit 0' EXIT
trap 'cleanup; exit 130' INT
trap 'cleanup; exit 143' TERMchmod +x ./run.sh# To be aware of TERM and INT signals call run.sh
# Running it with the --once flag at the end will shut down the agent after the build is executed
./run.sh "$@" & wait $!

當然大家也可以直接使用我已經做好了的鏡像:ccr.ccs.tencentyun.com/xinlai/tfsagnet:latest

這樣,代碼都不用抄了,多省事。相關環境變量如下所示:

環境變量說明
AZP_URLAzure DevOps 或Azure DevOps Server實例的 URL。
AZP_TOKEN密碼。PAT認證有問題,被我改成了negotiate認證。
AZP_AGENT_NAME代理名稱 (默認值:容器主機名) 。
AZP_POOL代理池名稱 (默認值:?Default) 。
AZP_WORK工作目錄 (默認值:?_work) 。

在Docker中運行

參考腳本:

docker run -e AZP_URL=<Azure DevOps instance> -e AZP_TOKEN=<密碼> -e AZP_AGENT_NAME=mydockeragent ccr.ccs.tencentyun.com/xinlai/tfsagnet:latest

但是現在的構建離不開Docker,那么Docker in Docker我們肯定是需要的,修改后參考腳本如下所示:

docker run --name docker-ag \
-e AZP_AGENT_NAME=docker-tx-ag \
-e AZP_URL=\
-e AZP_TOKEN=<密碼> \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /usr/bin/docker:/usr/bin/docker \
--user root \
--restart=always \
ccr.ccs.tencentyun.com/xinlai/tfsagnet:latest

使用portainer來管理Docker代理

在一臺服務器上跑了幾個實例,為了便于管理,我們可以運行一個portainer實例來進行管理,參考腳本如下:

docker run -d -p 80:9000 --restart=always -v /var/run/docker.sock:/var/run/docker.sock --name prtainer portainer/portainer

然后我們就可以登錄其Web管理界面來進行監控和管理:

658a20c88bf8677f26534a86dfa2a28b.png

portainer管理UI

我們可以在一臺服務器多跑幾個:

76abcefcdb6a2cb067ea0a3df4056236.png

Docker代理

運行了之后,我們可以在Azure DevOps的默認代理池看到他們:

3def41181609cc4e2ed62e0000de66c4.png

定時清理

基于容器構建很方便,但是費空間,尤其是高頻次構建,多運行時構建時,各種懸浮鏡像的存在,我們可以加個定時構建任務來進行清理,參考腳本如下:

docker system prune -a -f

這樣,50G的系統盤一拖3個代理,也是夠了。

最后

至此,整個教程到此就結束了。服務器推薦配置如下所示:

  • 磁盤大小:30~50G,如代碼文件過大可以適當增加空間以及增加自動清理的頻率

  • 內存:16~32G,如果只構建后端代碼,8G也是夠了,但是前端構建是個黑洞,很多代碼構建時沒個16G內存,會直接原地崩潰

  • CPU:4~8核

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/280097.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/280097.shtml
英文地址,請注明出處:http://en.pswp.cn/news/280097.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

微軟 word轉換pdf_如何將行轉換為Microsoft Word表中的列

微軟 word轉換pdfYou’ve created a table in Word and started to enter your data. Then, you realize that the table should be transposed, meaning the rows should be columns and vice versa. Rather than recreating the table and manually entering the data again,…

pycharm中如何正確配置pyqt5

網上看了幾個文章&#xff0c;不成功。這樣做才是正確姿勢&#xff1a; /Users/mac/anaconda3/bin/Designer.app /Users/mac/anaconda3/bin$ProjectFileDir$ pyuic5 $FileName$ -o $FileNameWithoutExtension$.py $ProjectFileDir$ 其它細節懶得說。 轉載于:https://www.cnblog…

JS常用的設計模式

持續更新JS常用的設計模式以及應用場景*以下內容為個人簡單理解以及摘抄部分網上demo組成&#xff0c;有錯誤請在下方評論指出?*# 何謂設計模式沒必要被高大上的名詞所嚇倒&#xff0c;日常coding中或許一個不了解各種設計模式的程序員可能自己其實已經用到了很多拋開官方的定…

如何在Photoshop中制作雙曝光圖像

Double exposure images are popular at the moment. Taylor Swift’s Style music video and the True Detective opening theme both used the effect. It’s a technique where two separate photos—typically a portrait and a landscape—are blended together into one …

記一次.NET 某安全生產系統 CPU爆高分析

一&#xff1a;背景 1.講故事今天是&#x1f40f;的第四天&#xff0c;頭終于不巨疼了&#xff0c;寫文章已經沒什么問題&#xff0c;趕緊爬起來寫。這個月初有位朋友找到我&#xff0c;說他的程序出現了CPU爆高&#xff0c;讓我幫忙看下怎么回事&#xff0c;簡單分析了下有兩點…

JDBC 學習筆記(一)—— JDBC 基礎

1. 什么是 JDBC JDBC&#xff0c;Java Database Connectivity&#xff08;Java 數據庫連接&#xff09;&#xff0c;是一組執行 SQL 語句的 Java API。 JDBC&#xff0c;是 Java SE&#xff08;Java Platform, Standard Edition&#xff09;標準的一部分。 Java 程序可以通過 J…

JavaScript享元模式

JavaScript享元模式 通過兩個例子的對比來凸顯享元模式的特點&#xff1a;享元模式是一個為了提高性能(空間復雜度)的設計模式&#xff0c;享元模式可以避免大量非常相似類的開銷。 第一實例&#xff0c;沒有使用享元模式&#xff0c;計算所花費的時間和空間使用程度。 要求為&…

mac屏幕截圖_如何在Mac上拍攝屏幕截圖

mac屏幕截圖On a Mac, you can take screenshots with a few quick keyboard shortcuts. But Mac OS X also includes more powerful screenshot tools, too. Here are some of the many ways you can get a screenshot on OS X. 在Mac上&#xff0c;您可以使用一些快速的鍵盤快…

實現 .Net 7 下的數據庫定時檢查

在軟件開發過程中&#xff0c;有時候我們需要定時地檢查數據庫中的數據&#xff0c;并在發現新增數據時觸發一個動作。為了實現這個需求&#xff0c;我們在 .Net 7 下進行一次簡單的演示。PeriodicTimer .Net 6 中新增了 PeriodicTimer 這個類&#xff0c;它可以用來創建一個定…

新手AS常見問題集錦

開發環境 以前開發android的時候可以使用eclipse&#xff0c;雖然現在也能使用eclipse&#xff0c;但是google已經不再支持使用eclipse開發android了。因為google有了自己的IDE---android studio&#xff0c;這個IDE我自己認為安裝的時候比較方便&#xff0c;唯一的缺點就是在下…

js進階 11-6 jquery如何獲取和設置元素的寬高(jquery多方法)

js進階 11-6 jquery如何獲取和設置元素的寬高&#xff08;jquery多方法&#xff09; 一、總結 一句話總結&#xff1a;jquery里面多是方法啊&#xff0c;比如jquery對象的寬高。所以取值是方法&#xff0c;賦值就是方法里面帶參數。 1、百度富文本編輯器ueditor如何設置寬高&a…

SparseArray代替HashMap

相信大家都明白&#xff0c;手機軟件的開發不同于PC軟件的開發&#xff0c;因為手機性能相對有限&#xff0c;內存也有限&#xff0c;所謂“寸土寸金”&#xff0c;可能稍有不慎&#xff0c;就會導致性能的明顯降低。Android為了方便開發者&#xff0c;特意在android.util這個包…

也許你曾經讀過他的書

我們愿用“能理能文、才華多元”來形容他。因為熱愛編程和游戲&#xff0c;所以他將愛好變成了職業&#xff0c;并在這條路上持續奔跑&#xff1b;因為熱愛分享&#xff0c;所以他堅持在博客上分享技術觀點并出版了關于 Azure、微軟游戲棧的書籍&#xff1b;因為熱愛挑戰&#…

python測試框架數據生成工具最全資源匯總

xUnit frameworks 單元測試框架frameworks 框架unittest - python自帶的單元測試庫&#xff0c;開箱即用unittest2 - 加強版的單元測試框架&#xff0c;適用于Python 2.7以及后續版本pytest - 成熟且功能強大的單元測試框架plugincompat - pytest的執行及兼容性插件nosetests -…

t30智能插座怎么設置_如何設置ConnectSense智能插座

t30智能插座怎么設置If you like the idea of smart outlets, but wish you had one with more than just one receptacle on it, the ConnectSense Smart Outlet is worth looking into. Here’s how to set it up and instantly get double the fun. 如果您喜歡智能插座的想法…

用鏈表和數組實現HASH表,幾種碰撞沖突解決方法

Hash算法中要解決一個碰撞沖突的辦法&#xff0c;后文中描述了幾種解決方法。下面代碼中用的是鏈式地址法&#xff0c;就是用鏈表和數組實現HASH表。 he/*hash table max size*/ #define HASH_TABLE_MAX_SIZE 40/*hash table大小*/ int hash_table_size0;/*.BH----------------…

安卓操作sqlite3,增刪改查

創建 layout <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"android:orientation"vertical"android:layout_width"match_parent"android:layo…

基于.NetCore開發博客項目 StarBlog - (23) 文章列表接口分頁、過濾、搜索、排序

1前言上一篇留的坑&#xff0c;火速補上。在之前的第6篇中&#xff0c;已經有初步介紹&#xff0c;本文做一些補充&#xff0c;已經搞定這部分的同學可以快速跳過&#xff0c;基于.NetCore開發博客項目 StarBlog - (6) 頁面開發之博客文章列表對標準的WebApi來說&#xff0c;分…

如何在Chrome中保存您當前的所有標簽,以便以后閱讀

Chrome allows you to open tabs from your last browsing session when you open the browser. However, what if you want to save your current set of tabs to re-open at any time? Chrome doesn’t provide a way to do that natively, but there is an easy workaround…

ubuntu 16.04(Windows 10雙系統+grub引導)無法進入tt1~tt6(NVIDIA驅動安裝相關-黑屏,login loop,分辨率)...

目錄 前言回顧最終解決&#xff1a;0.關閉x服務1.禁用nouveau2.加入3.更新4.查找匹配驅動5.選擇推薦版本6.等待安裝后重啟,nvidia-smi查看是否安裝成功,或者lsmod | grep nvidia&#xff0c;成功結果如下7.重啟x服務8.此時還不能進入圖形界面&#xff0c;因為nomodeset還在&…