硬核干貨| 如何利用K3s低成本在流水線中添加測(cè)試

作者介紹
Petro Kashlikov争舞,AWS技術(shù)客戶經(jīng)理。十分熱衷于容器技術(shù)耳鸯,并與客戶一起設(shè)計(jì)、部署和管理他們的工作負(fù)載/架構(gòu)膀曾。

現(xiàn)代化的微服務(wù)應(yīng)用程序堆棧县爬、CI/CD流水線、Kubernetes作為編排引擎以及每天成千上百的部署……這些聽(tīng)起來(lái)十分美好添谊,直到你發(fā)現(xiàn)你的Kubernetes開(kāi)發(fā)或staging環(huán)境被這些部署弄得混亂不堪并且一個(gè)開(kāi)發(fā)團(tuán)隊(duì)所做的更改會(huì)影響你的Kubernetes環(huán)境捌省。在本文中,我們將了解為什么這些外部更改會(huì)影響我們的Kubernetes環(huán)境以及如何避免這一影響碉钠。

之所以會(huì)出現(xiàn)這一問(wèn)題,是因?yàn)樵趯㈢R像推送到鏡像倉(cāng)庫(kù)并部署我們的資源之前卷拘,我們?cè)诹魉€中進(jìn)行了各種代碼檢查和鏡像掃描喊废。但是,因?yàn)榱魉€內(nèi)部沒(méi)有可用的Kubernetes集群栗弟,因此在流水線本身中沒(méi)有進(jìn)行適當(dāng)?shù)募苫騿卧獪y(cè)試污筷。實(shí)際上,我們是在部署后測(cè)試我們的更改。

面對(duì)這個(gè)問(wèn)題瓣蛀,有一個(gè)解決方案就是在每次構(gòu)建陆蟆、測(cè)試更改時(shí)配置一個(gè)干凈的Kubernetes集群,然后再將其清除惋增。但是這十分耗時(shí)也不劃算叠殷。相反,我們可以使用由Rancher Labs推出的開(kāi)源诈皿、輕量級(jí)的Kubernetes發(fā)行版K3s林束,與Amazon和AWS CodePipeline一起解決這個(gè)問(wèn)題。

什么是K3s稽亏?

K3s是一個(gè)開(kāi)源壶冒、輕量的Kubernetes發(fā)行版,大小小于100MB截歉,專為物聯(lián)網(wǎng)胖腾、邊緣和CI/CD環(huán)境設(shè)計(jì)。啟動(dòng)時(shí)間僅需40秒左右瘪松。

更有趣的是咸作,對(duì)于CI/CD用例,我們可以在Docker容器內(nèi)運(yùn)行K3s凉逛。Rancher還提供了另一個(gè)名為k3d的工具性宏,它是一個(gè)輕量級(jí)的wrapper,可以在Docker容器內(nèi)運(yùn)行K3s状飞。在這種情況下毫胜,這個(gè)package的大小約為10MB,啟動(dòng)時(shí)間更快诬辈,約為15-20秒酵使。

現(xiàn)在我們開(kāi)始了解如何實(shí)現(xiàn)這一解決方案。

前期準(zhǔn)備

要完成這一教程焙糟,我們需要:

  • 一個(gè)AWS賬號(hào)
  • 一個(gè)Github賬號(hào)
  • 安裝并配置AWS CLI口渔、kubectl、eksctl功能穿撮。你可以根據(jù)以下鏈接指引安裝eksctl:

https://docs.aws.amazon.com/eks/latest/userguide/getting-started-eksctl.html

配置Amazon EKS集群

有很多方法可以進(jìn)行配置缺脉,包括使用AWS管理控制臺(tái)、AWS CLI等悦穿。我們推薦使用eksctl攻礼,但不管你喜歡什么方式都可以使用,并根據(jù)你的喜好修改節(jié)點(diǎn)類型和區(qū)域栗柒。集群配置一般需要15分鐘左右礁扮。

eksctl create cluster \
--name k3s-lab \
--version 1.16 \
--nodegroup-name k3s-lab-workers \
--node-type t2.medium \
--nodes 2 \
--alb-ingress-access \
--region us-west-2

在本練習(xí)中,我們使用 t2.medium 實(shí)例系列。如果你在生產(chǎn)環(huán)境中啟動(dòng)Amazon EKS集群太伊,請(qǐng)記住使用適當(dāng)?shù)膶?shí)例類型雇锡。

集群配置完成后,我們使用命令來(lái)驗(yàn)證它是否已經(jīng)啟動(dòng)僚焦,以及是否正確配置了 kubectl:

kubectl get nodes

我們的輸出應(yīng)該如下所示:

NAME                             STATUS   ROLES     AGE       VERSION
ip-192-168-12-121.ec2.internal   Ready    <none>    82s       v1.16.8-eks-e16311
ip-192-168-38-246.ec2.internal   Ready    <none>    80s       v1.16.8-eks-e16311

設(shè)置AWS CodePipeline

1锰提、 設(shè)置ACCOUNT_ID變量:

ACCOUNT_ID=$(aws sts get-caller-identity --output text --query 'Account')

2、 在CodePipeline中叠赐,我們使用AWS CodeBuild來(lái)部署示例Kubernetes服務(wù)欲账。這需要一個(gè)能與Amazon EKS集群交互的AWS IAM(身份識(shí)別與訪問(wèn)管理)角色,并添加一個(gè)內(nèi)聯(lián)策略芭概,以便在CodeBuild階段使用赛不。該策略將允許AWS CodeBuild通過(guò)kuebctl與Amazon EKS集群進(jìn)行交互。執(zhí)行以下命令來(lái)創(chuàng)建角色并附加策略:

TRUST="{ \"Version\": \"2012-10-17\", \"Statement\": [ { \"Effect\": \"Allow\", \"Principal\": { \"AWS\": \"arn:aws:iam::${ACCOUNT_ID}:root\" }, \"Action\": \"sts:AssumeRole\" } ] }"
echo '{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "eks:Describe*", "Resource": "*" } ] }' > /tmp/iam-role-policy
aws iam create-role --role-name EksWorkshopCodeBuildKubectlRole --assume-role-policy-document "$TRUST" --output text --query 'Role.Arn'
aws iam put-role-policy --role-name EksWorkshopCodeBuildKubectlRole --policy-name eks-describe --policy-document file:///tmp/iam-role-policy

3罢洲、 既然我們已經(jīng)創(chuàng)建了IAM角色踢故,那么我們將為Amazon EKS集群添加這一角色到aws-auth ConfigMap。一旦包含此角色惹苗,kubectl就可以通過(guò)IAM角色與Amazon EKS集群進(jìn)行交互殿较。

ROLE="    - rolearn: arn:aws:iam::$ACCOUNT_ID:role/EksWorkshopCodeBuildKubectlRole\n      username: build\n      groups:\n        - system:masters"
kubectl get -n kube-system configmap/aws-auth -o yaml | awk "/mapRoles: \|/{print;print \"$ROLE\";next}1" > /tmp/aws-auth-patch.yml 
kubectl patch configmap/aws-auth -n kube-system --patch "$(cat /tmp/aws-auth-patch.yml)"

4、 接下來(lái)桩蓉,我們將fork示例Kubernetes服務(wù)以便我們可以修改repo并觸發(fā)構(gòu)建淋纲。登錄到Github并fork示例服務(wù)到所選賬戶。參考Kubernetes服務(wù)示例了解更多信息院究。鏡像倉(cāng)庫(kù)被fork后洽瞬,將其克隆到本地環(huán)境,這樣我們就可以使用我們最喜歡的IDE或文本編輯器來(lái)處理文件业汰。

git clone https://github.com/YOUR-USERNAME/eks-workshop-sample-api-service-go.git

5伙窃、 為了讓CodePipeline能夠接收來(lái)自GitHub的回調(diào),我們必須生成一個(gè)個(gè)人的訪問(wèn)令牌样漆。一旦創(chuàng)建为障,訪問(wèn)令牌將被存儲(chǔ)在一個(gè)安全的程序集(enclave)中,并被重復(fù)使用放祟。只有在第一次運(yùn)行時(shí)鳍怨,或者需要生成新的密鑰時(shí),才需要這一步跪妥。

6京景、 接著,我們將使用AWS CloudFormation創(chuàng)建Codepipeline骗奖。導(dǎo)航到AWS管理控制臺(tái)以創(chuàng)建CloudFormation堆棧。控制臺(tái)啟動(dòng)后执桌,鍵入Github用戶名鄙皇、個(gè)人訪問(wèn)令牌(在前一個(gè)步驟已經(jīng)創(chuàng)建)以及Amazon EKS集群名稱(k3s-lab)。然后仰挣,選擇確認(rèn)并點(diǎn)擊創(chuàng)建堆棧伴逸。這一步大概需要花費(fèi)10分鐘。

創(chuàng)建CodePipeline之后膘壶,我們可以在CodePipeline控制臺(tái)中創(chuàng)建狀態(tài)并使用以下命令驗(yàn)證部署是否應(yīng)用到我們的集群中:

kubectl describe deployment hello-k8s

將k3d添加到AWS Codepipeline

現(xiàn)在错蝴,我們?cè)趂ork的repo里修改buidspec.yaml并使用k3d添加單元測(cè)試。

我們將逐步介紹所需的修改颓芭,這些修改可以手動(dòng)完成顷锰。或者亡问,在本節(jié)末尾也為你提供了完整的buildspec.yml文件官紫。

1、 在CodeBuild環(huán)境中安裝k3d:

- curl -sS https://raw.githubusercontent.com/rancher/k3d/main/install.sh | TAG=v1.7.0 bash

2州藕、 在構(gòu)建階段創(chuàng)建k3s集群并等待集群?jiǎn)?dòng)束世,這大概需要花費(fèi)20秒:

- k3d create
- sleep 20

3、 為k3s集群配置kubectl

- export KUBECONFIG="$(k3d get-kubeconfig --name='k3s-default')"

4床玻、 默認(rèn)情況下毁涉,Amazon EKS 集群節(jié)點(diǎn)被 eksctl 配置為可以訪問(wèn)從 Amazon Elastic Container Registry (Amazon ECR) 鏡像庫(kù)中拉取鏡像。然而锈死,非Amazon EKS 集群需要為此進(jìn)行額外配置贫堰。在文檔中找到這個(gè)配置的說(shuō)明。因?yàn)橛袔讉€(gè)步驟馅精,我把它們移到一個(gè)單獨(dú)的腳本(create_secret.sh)中严嗜,并在buildspec.yml文件里面調(diào)用:

- ./create_secret.sh

將文件create_secret.sh添加到forked repository的工作文件夾中,其上下文如下:

SECRET_NAME=$AWS_REGION-ecr-registry
 TOKEN=`aws ecr get-authorization-token --output text --query authorizationData[].authorizationToken | base64 -d | cut -d: -f2`
 echo "ENV variables setup done."
 kubectl create secret docker-registry $SECRET_NAME \
 --docker-server=https://$REPOSITORY_URI \
 --docker-username=AWS \
 --docker-password="${TOKEN}" \
 --docker-email=DUMMY_DOCKER_EMAIL
 kubectl patch serviceaccount default -p '{"imagePullSecrets":[{"name":"'$SECRET_NAME'"}]}'

5洲敢、 將我們的流水線應(yīng)用程序資源到k3d集群并等待資源啟動(dòng)漫玄,這大概需要花費(fèi)20秒:

- kubectl apply -f hello-k8s.yml
- sleep 20

配置測(cè)試

在這一步中,我們可以運(yùn)行我們的單元/集成測(cè)試压彭。對(duì)于本例睦优,我們已經(jīng)提供了一個(gè)簡(jiǎn)單的腳本來(lái)hit我們服務(wù)的endpoint。我們可以從我們的堆棧中部署其他必要的微服務(wù)或服務(wù)進(jìn)行集成測(cè)試壮不。

- ./unit_test.sh

將文件 unit_test.sh 添加到 forked repository 的工作文件夾中汗盘,其上下文如下:

#!/bin/sh
set -e
api_host=$(kubectl get svc hello-k8s -o json | jq -r .status.loadBalancer.ingress[].ip)
curl -m 2 $api_host

檢查測(cè)試是否成功

最后一步是檢查測(cè)試是否成功并且將我們的應(yīng)用程序部署到Amazon EKS集群。如果測(cè)試失敗询一,我們的Codepipeline就會(huì)失敗隐孽,不會(huì)部署到Amazon EKS癌椿。CodeBuild有個(gè)內(nèi)置的變量CODEBUILD_BUILD_SUCCEEDING來(lái)指示構(gòu)建階段的狀態(tài)。我們會(huì)在代碼中使用它:

- bash -c "if [ /"$CODEBUILD_BUILD_SUCCEEDING/" == /"0/" ]; then exit 1; fi" 
- echo Build stage successfully completed on `date`

buildspec.yml

---
version: 0.2
phases:
  install:
    commands:
      - curl -sS -o aws-iam-authenticator https://amazon-eks.s3-us-west-2.amazonaws.com/1.10.3/2018-07-26/bin/linux/amd64/aws-iam-authenticator
      - curl -sS -o kubectl https://amazon-eks.s3-us-west-2.amazonaws.com/1.14.6/2019-08-22/bin/linux/amd64/kubectl
      - curl -sS https://raw.githubusercontent.com/rancher/k3d/main/install.sh | TAG=v1.7.0 bash
      - chmod +x ./kubectl ./aws-iam-authenticator
      - export PATH=$PWD/:$PATH
      - apt-get update && apt-get -y install jq python3-pip python3-dev && pip3 install --upgrade awscli
  pre_build:
      commands:
        - TAG="$REPOSITORY_NAME.$REPOSITORY_BRANCH.$ENVIRONMENT_NAME.$(date +%Y-%m-%d.%H.%M.%S).$(echo $CODEBUILD_RESOLVED_SOURCE_VERSION | head -c 8)"
        - sed -i 's@CONTAINER_IMAGE@'"$REPOSITORY_URI:$TAG"'@' hello-k8s.yml
        - $(aws ecr get-login --no-include-email)
  build:
    commands:
      - docker build --tag $REPOSITORY_URI:$TAG .
      - docker push $REPOSITORY_URI:$TAG
      # Creating k3d cluster
      - k3d create
      # Waiting for cluster creation for 20 seconds
      - sleep 20
      # Configuring kubectl for k3d cluster
      - export KUBECONFIG="$(k3d get-kubeconfig --name='k3s-default')"
      # Creating secret as per https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#add-image-pull-secret-to-service-account
      # to enable k3d cluster pull images from ECR
      - ./create_secret.sh
      # Applying our service and deployment manifest
      - kubectl apply -f hello-k8s.yml
      # Waiting for pods and service to come up
      - sleep 20
      # Running unit test
      - ./unit_test.sh
  post_build:
    commands:
      # Checking if build phase including unit test completed successfully, if not we don't proceed with deployment
      - bash -c "if [ /"$CODEBUILD_BUILD_SUCCEEDING/" == /"0/" ]; then exit 1; fi"
      - echo Build stage successfully completed on `date`
      - CREDENTIALS=$(aws sts assume-role --role-arn $EKS_KUBECTL_ROLE_ARN --role-session-name codebuild-kubectl --duration-seconds 900)
      - export KUBECONFIG=$HOME/.kube/config
      - export AWS_ACCESS_KEY_ID="$(echo ${CREDENTIALS} | jq -r '.Credentials.AccessKeyId')"
      - export AWS_SECRET_ACCESS_KEY="$(echo ${CREDENTIALS} | jq -r '.Credentials.SecretAccessKey')"
      - export AWS_SESSION_TOKEN="$(echo ${CREDENTIALS} | jq -r '.Credentials.SessionToken')"
      - export AWS_EXPIRATION=$(echo ${CREDENTIALS} | jq -r '.Credentials.Expiration')
      - aws eks update-kubeconfig --name $EKS_CLUSTER_NAME
      - kubectl apply -f hello-k8s.yml
      - printf '[{"name":"hello-k8s","imageUri":"%s"}]' $REPOSITORY_URI:$TAG > build.json
artifacts:
  files: build.json

所有更改都完成并且新文件已經(jīng)在我們本地forked repository之后菱阵,我們需要提交這些更改踢俄,這樣CodePipeline可以接收它們,并將它們應(yīng)用到我們的流水線中晴及。

git add .
git commit -m "k3d modified pipeline"
git push

當(dāng)我們推送這些更改之后都办,我們可以訪問(wèn)CodePipeline控制臺(tái)并檢查流水線的狀態(tài)和日志。

圖片

在Build部分選擇Details虑稼。在這里琳钉,我們可以在Build Logs下檢查我們的流水線運(yùn)行過(guò)程中發(fā)生了什么。

圖片

清 理

為了避免產(chǎn)生多余的費(fèi)用蛛倦,我們需要進(jìn)行一些清理步驟:

1歌懒、 刪除為CodePipeline創(chuàng)建的CloudFormation堆棧。打開(kāi)CloudFormation管理控制臺(tái)胰蝠,選擇eksws-codeepipeline堆棧旁邊的方框歼培,選擇刪除,然后在彈出的窗口中確認(rèn)刪除茸塞。

圖片

2躲庄、 刪除Amazon ECR repository。打開(kāi)Amazon ECR管理控制臺(tái)钾虐,選擇以eksws開(kāi)頭的repository名稱旁邊的方框噪窘。選擇 "Delete",然后確認(rèn)刪除效扫。

圖片

3倔监、清空并刪除 CodeBuild 用于構(gòu)建工件的 Amazon S3 bucket。bucket 名稱以 eksws-codepipeline 開(kāi)頭菌仁。

選擇 bucket浩习,然后選擇 Empty。選擇Delete來(lái)刪除該 bucket济丘。

圖片

4谱秽、 最后,使用以下命令刪除Amazon EKS集群:

eksctl delete cluster --name=k3s-lab

總 結(jié)

在本文中摹迷,我們探討了如何使用開(kāi)源疟赊、輕量級(jí)的Kubernetes發(fā)行版K3s,將單元和集成測(cè)試添加到Amazon EKS CI/CD流水線中峡碉。如果你在Amazon EKS部署中使用了不同的CI/CD工具近哟,你也可以輕松地將K3s納入其中。

原文鏈接:
https://aws.amazon.com/cn/blogs/opensource/using-the-k3s-kubernetes-distribution-in-an-amazon-eks-ci-cd-pipeline/

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末鲫寄,一起剝皮案震驚了整個(gè)濱河市吉执,隨后出現(xiàn)的幾起案子疯淫,更是在濱河造成了極大的恐慌,老刑警劉巖戳玫,帶你破解...
    沈念sama閱讀 221,635評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件峡竣,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡量九,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)颂碧,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)荠列,“玉大人,你說(shuō)我怎么就攤上這事载城〖∷疲” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,083評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵诉瓦,是天一觀的道長(zhǎng)川队。 經(jīng)常有香客問(wèn)我,道長(zhǎng)睬澡,這世上最難降的妖魔是什么固额? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,640評(píng)論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮煞聪,結(jié)果婚禮上斗躏,老公的妹妹穿的比我還像新娘。我一直安慰自己昔脯,他們只是感情好啄糙,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,640評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著云稚,像睡著了一般隧饼。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上静陈,一...
    開(kāi)封第一講書(shū)人閱讀 52,262評(píng)論 1 308
  • 那天燕雁,我揣著相機(jī)與錄音,去河邊找鬼窿给。 笑死贵白,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的崩泡。 我是一名探鬼主播禁荒,決...
    沈念sama閱讀 40,833評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了遵班?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,736評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤洗搂,失蹤者是張志新(化名)和其女友劉穎热康,沒(méi)想到半個(gè)月后沛申,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,280評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡姐军,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,369評(píng)論 3 340
  • 正文 我和宋清朗相戀三年铁材,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片奕锌。...
    茶點(diǎn)故事閱讀 40,503評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡著觉,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出惊暴,到底是詐尸還是另有隱情饼丘,我是刑警寧澤,帶...
    沈念sama閱讀 36,185評(píng)論 5 350
  • 正文 年R本政府宣布辽话,位于F島的核電站肄鸽,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏油啤。R本人自食惡果不足惜典徘,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,870評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望村砂。 院中可真熱鬧烂斋,春花似錦、人聲如沸础废。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,340評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)评腺。三九已至帘瞭,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間蒿讥,已是汗流浹背蝶念。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,460評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留芋绸,地道東北人媒殉。 一個(gè)月前我還...
    沈念sama閱讀 48,909評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像摔敛,于是被迫代替她去往敵國(guó)和親廷蓉。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,512評(píng)論 2 359

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