Utolsó részhez érkezett a CI/CD bemutatóm. A CI/CD „CD” része a Continuous Delivery: folyamatos szállítás. Saját szavaimmal: folyamatos frissítése az alkalmazásnak egy K8s rendszerben, amihez minden szükséges adatot egy git repóból fog megszerezni.
Van egy git repónk, ami a konténer készítéséért felel, és van egy git repónk, ami az alkalmazásunk Kubernetesbeli manifestjeit tárolja. Ezek lehetnek akár egy repóban is, rád bízom a döntést. Én a szeparáció miatt csináltam két független repót. Most bemutatok két módszert, amivel teljessé tesszük a CI/CD folyamatunkat.
Természetesen itt is el kell mondanom, nem biztos, hogy egy prod. alkalmazást full automatán kell frissíteni. Én annak vagyok a híve, hogy a teszt/dev/uat környezetekre mehet a friss konténer, de a prodra inkább kézzel rakom ki, miután alaposan letesztelték.
Az ArgoCD mindkét megközelítést támogatja. Biztos észrevettétek, de a CD nem véletlen az ArgoCD nevében 🙂
1. módszer: a git repóban módosítom a friss konténer verzióját (tag)
Vegyük elő a gitea workflow fájlunkat, és egészítsük ki egy új szakasszal (job):
name: Gitea Actions Demo
run-name: ${{ gitea.actor }} Gitea Actions CI demo 🚀
on:
push:
paths:
- 'build/apache-demo/Dockerfile'
- 'build/apache-demo/vars.conf'
schedule:
- cron: '0 5 * * SAT' # UTC-ben értendő
workflow_dispatch:
jobs:
Build apache-demo image:
runs-on: ubuntu-24.04
steps:
- name: Check out repository code
uses: actions/checkout@v4
- name: List files in the repository
run: |
ls -lR ${{ gitea.workspace }}
- name: Build apache-demo
run: |
cd build/apache-demo
. vars.conf
hash=${{env.GITHUB_SHA}}
LCD=$(git --no-pager log -1 --format="%ai")
docker build --build-arg BUILDDATE="$LCD" --network=host --rm --progress=plain -t $IMAGEBUILD${hash::10} .
docker images | egrep "TAG|$BUILD.${hash::10}"
- name: Send email on failure
if: failure()
uses: dawidd6/action-send-mail@v6
with:
server_address: ${{ vars.SMTP_SERVER }}
server_port: 25
ignore_cert: true
subject: "Az apache-demo build sikertelen"
to: ${{ vars.SMTP_TO }}
from: ${{ vars.SMTP_FROM }}
body: "Az apache-demo build hibára futott!"
Test apache-demo image:
needs: Build apache-demo image
runs-on: ubuntu-24.04
steps:
- name: Check out repository code
uses: actions/checkout@v4
- name: 1. start apache-demo container
run: |
hash=${{env.GITHUB_SHA}}
cd build/apache-demo
. vars.conf
docker run --rm -d --name $CONTAINERNAME -p $EXTPORT:$INTPORT $IMAGEBUILD
sleep 1
docker ps -a | grep $CONTAINERNAME
- name: 2. curl header test
run: |
cd build/apache-demo
. vars.conf
curl --silent -I http://$EXTIP:$EXTPORT/
- name: 3. check apache-demo version
run: |
cd build/apache-demo
. vars.conf
docker exec $CONTAINERNAME httpd -v
curl --silent -I http://$EXTIP:$EXTPORT/ | grep "^Server: Apache"
- name: 4. check apache-demo syntax
run: |
cd build/apache-demo
. vars.conf
docker exec $CONTAINERNAME httpd -t
- name: 5. check apache-demo login page
run: |
cd build/apache-demo
. vars.conf
if [[ $(curl --silent http://$EXTIP:$EXTPORT/ | grep -c "Ez egy demo oldal egy apache") == 1 ]]; then echo test success; else exit 255; fi
- name: 6. print index.html
run: |
cd build/apache-demo
. vars.conf
curl --silent http://$EXTIP:$EXTPORT/
- name: last step, stop apache-demo container
run: |
cd build/apache-demo
. vars.conf
docker stop $CONTAINERNAME
- name: Send email on failure
if: failure()
uses: dawidd6/action-send-mail@v6
with:
server_address: ${{ vars.SMTP_SERVER }}
server_port: 25
ignore_cert: true
subject: "Az apache-demo teszt sikertelen"
to: ${{ vars.SMTP_TO }}
from: ${{ vars.SMTP_FROM }}
body: "Az apache-demo teszt hibára futott!"
Push apache-demo image to registry:
needs: Test apache-demo image
runs-on: ubuntu-24.04
steps:
- name: Check out repository code
uses: actions/checkout@v4
- name: Push apache-demo image
run: |
hash=${{env.GITHUB_SHA}}
cd build/apache-demo
. vars.conf
docker tag $IMAGEBUILD $IMAGELATEST
docker push $IMAGEBUILD
docker push $IMAGELATEST
- name: Send email on failure
if: failure()
uses: dawidd6/action-send-mail@v6
with:
server_address: ${{ vars.SMTP_SERVER }}
server_port: 25
ignore_cert: true
subject: "Az apache-demo push sikertelen"
to: ${{ vars.SMTP_TO }}
from: ${{ vars.SMTP_FROM }}
body: "Az apache-demo push hibára futott!"
Deploy an application to K8s:
needs: Push apache-demo image to registry
runs-on: ubuntu-24.04
steps:
- name: Check out repository code
uses: actions/checkout@v4
- name: update apache-demo (1&2) application in git
run: |
hash=${{env.GITHUB_SHA}}
LAST_COMMIT=$(git log --format=%B -n 1 | head -n 1)
cd build/apache-demo
. vars.conf
git config --global user.email "${{ vars.SMTP_FROM }}"
git config --global user.name "${{ vars.NAME }}"
git clone http://msandor:${{ secrets.ARGOCD_TOKEN }}@192.168.5.213:3003/msandor/argocd.git
cd argocd/apache-demo
old=$(grep image deployment.yaml | cut -c 16-)
echo -e "\nOLD: "$old"\nNEW: "$IMAGEBUILD"\n" # debug
if [ "$old" = "$IMAGEBUILD" ]; then echo "No new commit, skipping."; exit 0; fi
sed 's|'"$old"'|'"$IMAGEBUILD"'|g' -i deployment.yaml
git commit -m "${LAST_COMMIT} (CI hash: ${hash::10})" deployment.yaml
cd ../apache-demo2
old=$(grep tag values.yaml | cut -c 8-)
echo -e "\nOLD: "$old"\nNEW: "$BUILD.${hash::10}"\n" # debug
sed 's|'$old'|'$BUILD.${hash::10}'|g' -i values.yaml
git commit -m "${LAST_COMMIT} (CI hash: ${hash::10})" values.yaml
git push --verbose
- name: Send email on failure
if: failure()
uses: dawidd6/action-send-mail@v6
with:
server_address: ${{ vars.SMTP_SERVER }}
server_port: 25
ignore_cert: true
subject: "Az apache-demo deploy sikertelen"
to: ${{ vars.SMTP_TO }}
from: ${{ vars.SMTP_FROM }}
body: "Az apache-demo deploy hibára futott!"
- name: Send email on success
if: success()
uses: dawidd6/action-send-mail@v6
with:
server_address: ${{ vars.SMTP_SERVER }}
server_port: 25
ignore_cert: true
subject: "Az apache-demo build és deploy sikeres"
to: ${{ vars.SMTP_TO }}
from: ${{ vars.SMTP_FROM }}
body: "Az apache-demo build és deploy sikeresen lefutott!"
Mit csinál a 4. job?
124. sortól a végéig. Bár az érdemi munkát egyetlen step végzi: 130.-150. sorok között.
Éles szeműek kiszúrhatták, hogy a gitea szerverem portja megváltozott. Ennek a semaphore ui az oka. Pontosabban az a tény, hogy vele menedzselem a proxmox teszt klaszterem, emiatt foglalt lett a gitea korábbi 3000-es portja. Így a giteának költöznie kellett.
Szóval mi történik az update apache-demo(2) application nevű lépésben?
- változóba rakja az utolsó git commit rövid hash-ét és commithoz tartozó megjegyzést
- letölti azt a git repót, ahol Kubernetes manifesteket tárolom
- mindkét változatban lecseréli a tag-et az újra (a normál yaml fájlban is és a helm chartban is)
- ugyanazzal a kommenttel commitolja a változtatásokat
- végül feltölti a git repóba (git push)
- ha nem volt commit, akkor kilép, ez azért jó, mert az időzített futáskor nincs commit
Az érdemi munkát az ArgoCD fogja végezni.
Mi ennek a módszernek az előnye?
Az, hogy a gitben ugyanaz a tag szerepel, mint a futó app tag-je.
2. módszer: közvetlenül a K8s fürtön frissítem a podot
Erre akkor lehet szükség, ha nem engedélyezik az ArgoCD használatát, ám azt elvárják, hogy Helm Chartból telepíts.
Vegyük elő a korábbi gitea workflow fájlunkat, és adjunk hozzá egy új blokkot. Szúrjuk be a 151. sorba, ahol most ez áll: – name: Send email on failure.
- name: update apache-demo(helm) application in K8s
run: |
curl -fsSL https://packages.buildkite.com/helm-linux/helm-debian/gpgkey | gpg --dearmor | tee /usr/share/keyrings/helm.gpg > /dev/null
echo "deb [signed-by=/usr/share/keyrings/helm.gpg] https://packages.buildkite.com/helm-linux/helm-debian/any/ any main" > /etc/apt/sources.list.d/helm-stable-debian.list
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.34/deb/Release.key | gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
chmod 644 /etc/apt/keyrings/kubernetes-apt-keyring.gpg
apt-get update -qq
apt-get install helm kubectl -y -qq 2>/dev/null >/dev/null
echo "${{ secrets.KUBECONFIG_DEMO }}" > /tmp/kubeconfig.yaml
echo "DEBUG: a Kubernetes fürt API-ja: "$(grep server /tmp/kubeconfig.yaml | awk '{print $2}')
export KUBECONFIG=/tmp/kubeconfig.yaml
hash=${{env.GITHUB_SHA}}
cd build/apache-demo
. vars.conf
cd argocd/apache-demo2 # kell a values.yaml fájl
echo -e "\nDEBUG: kubectl get nodes:"
kubectl get nodes; echo
helm upgrade --install apache-demo2 . -f values.yaml --set image.repository=$REGISTRY/msandor/apache-demo --set image.tag=$BUILD.${hash::10} --namespace default --create-namespace --atomic
echo -e "\nhelm list:"
helm list -n default
Rövid ismertető az új taszkról:
3.-8. sor: a helm és a kubectl nem része a runner lemezképnek, ezért feltelepítem
9. sor: fájlba írom a kubeconfigot egy gitea secretből
10. sor: kiíratom a szerver IP címét és API portját (debug jelleggel)
11. sor: exportálom a KUBECONFIG-ot, ez kell a kubectl-nek és a helmnek
16.-17. sor: lekérem a klaszter node-jainak listáját (debug jelleggel)
18. sor: a lényeg, frissítem a klaszteren az alkalmazást
Ezzel még nem végeztünk, kell egy secret a gitea CICD repóhoz, aminek a tartalmát az alábbi paranccsal tudjuk lekérdezni. Az én fürtöm neve: kind-kind-demo
kubectl config view --minify --flatten --context=kind-kind-demo
Most menjünk a gitea CICD repó beállításaihoz, majd actions -> secrets:

A neve KUBECONFIG_DEMO legyen, a tartalma pedig az, amit a fenti parancs kiadott!
A git push után futtassuk le a workflowt:

Lássuk az új taszkunk kimenetét:

Ezzel kész is vagyunk!
Mi ennek a módszernek az előnye?
Hogy nincs szükség ArgoCD-re.