GitOps入門與實踐:如何集成Git和K8S?

也許你之前聽說過GitOps,但是對其並不瞭解。在本文中,我將對其進行簡單介紹,它其實是一個應用程序開發和管理中的一個術語,其核心思想是將應用系統的聲明性基礎架構和應用程序存放在Git的版本控制庫中。我們將介紹GitOps是什麼,它將如何影響組織以及如何與Kubernetes保持同步。


GitOps入門與實踐:如何集成Git和K8S?


什麼是GitOps


GitOps是一種實現持續交付的模型,利用Git開發工具對雲原生應用程序進行操作和管理。當將應用程序部署到Kubernetes時,Git應該是唯一的事實來源。當開發人員更改應用程序時,Git將自動把它們push到Kubernetes進行部署。而且,如果Kubernetes內的運行狀態發生變化但與Git內的狀態不一致,則它們會從Git內恢復到已知狀態。


GitOps與CI/CD:它們之間有什麼聯繫?


GitOps和CI/CD是十分重要的工作夥伴。CI/CD可以讓開發人員持續迭代、開發和部署應用程序。而迭代通常通過一個Git配置倉庫進行(儘管也會有其它配置倉庫)。在部署/交付階段,構建的基於容器的應用程序被“push”到Kubernetes進行部署。GitOps會通過Kubernetes使用“pull”的方法來增強CI/CD模型,從而將運維層面帶入部署/交付中。


但是,如果有人更改了Kubernetes集群中運行的某些內容,會發生什麼?我們將使用Git作為聲明性部署工具的主要事實來源,並利用其他工具在出現差異時向我們發出警報。此外,通過利用可以識別運行狀態和聲明狀態之間差異的工具,Kubernetes可以修復為已知/聲明的運行狀態。


注意:持續集成和持續開發是互補但獨立的過程。在理想狀態下,GitOps會將批處理規模拆分為單件流程,每次只處理一個單元。但是,由於CI和CD流程發生在不同的組中,因此組織之間的流程可能會有所不同。


GitOps和應用程序生命週期


讓我們從應用程序生命週期的視角來看一下GitOps的作用。在典型的生命週期中,應用程序會經歷多個狀態,包括:


  • 代碼
  • 構建
  • 創建鏡像
  • 測試
  • 發佈


而使用GitOps,這些狀態將會擴展為:


  • 部署
  • 在Git倉庫中監控更改
  • 日誌更改和事件
  • 發生更改時發出警報,並於現有的監控/告警系統集成
  • 更新


在GitOps操作模型下,當應用程序發佈時,Kubernetes需要確保其按預期運行。同時,Kubernetes通過確保其穩定性和可用性來管理應用程序的運維工作。如果一個開發人員通過Git更改了該應用程序,Kubernetes將會接受聲明並根據需要應用它。


GitOps帶來了什麼?


  • GitOps為應用程序提供一個操作模型,它可以確保Git提供一個框架來統一應用程序的運行、操作和持續開發。
  • 作為CI/CD流水線的一部分,GitOps為應用程序構建/交付與運行它的位置之間提供了粘合劑。
  • 在Kubernetes平臺中,Git為應用程序的開發和運維提供了唯一的事實來源。
  • 應用程序交付和平臺管理都是聲明式的,同時還能通過Git進行版本控制
  • Git可以控制回滾、升級以及更改
  • 開發人員不需要知道如何操作運維平臺(如Kubernetes),無需瞭解複雜的部署交付流程,僅需使用熟悉的工具發佈新功能即可。極大提升開發者體驗。
  • Git控制並修正差異或“漂移”
  • GitOps利用審核、監控以及回滾功能來增加應用程序發佈的可靠性和穩定性

最後,儘管在GitOps模式下還有很多工作要做,但是GitOps、DevOps以及現有CI/CD模式之間存在十分明顯的協同作用。GitOps提供了一種用於將應用程序交付到Kubernetes平臺的模型,該模型確保了Git是唯一的事實來源並且充分利用Kubernetes平臺上的功能。但值得注意的是,GitOps不能替代工具。恰恰相反,GitOps通過聲明性的流程和工具來強化流程、提高其成熟度並幫助團隊交付應用程序。


GitOps實踐:FluxCD Demo


FluxCD(或Flux)是一個很棒的工具,它可以將Git和Kubernetes集成起來。Flux本質上是一個Kubernetes Operator,這意味著,你作為一個管理員可以將其安裝到Kubernetes 以管理Git和原生Kubernetes之間的集成。


在Kubernetes中,Operator是Kubernetes原生平臺的擴展,是一種自定義資源的模式,該自定義資源主要用於管理應用程序及其組件。這意味著,在Kubernetes內部Operator的幫助下,所需狀態(如運行狀態)將不斷檢查和調整以符合Git倉庫聲明的內容。Flux可以集成到你現有的CI/CD工具集中,以進行其他工作流程、權限批准和審核。在Kubernetes中,Flux會監控你通過配置聲明的Git倉庫是否發生更改,並且如果 Kubernetes Pod上在本地發生了不應發生的更改,Flux將會把Kubernetes更新到所需的運行狀態。請記住,Git是事實來源。Flux Operator會檢測到這一點,並將正在運行的配置更改回聲明的狀態。


以下demo,我將會展示如何安裝和實現Flux。


前期準備


你將需要:


  • 一個Docker Hub鏡像倉庫,你可以將Flaskapp docker鏡像上傳到此處
  • 一個Git Repo並連接它,然後你可以在整個演示過程中根據需要用你的設置替換“< >”中的任何內容


具體步驟


  • 安裝Kubernetes
  • 安裝並配置fluxctl,Flux部署的原生安裝程序
  • 配置Flux以連接到Git Repo
  • 在Git Repo中升級deployment manifest
  • 升級容器鏡像並同步
  • 配置漂移(drift)並同步


你可以使用以下配置進行測試或演示。它包括Flask應用程序的Docker file以及Kubernetes deployment/配置文件。在演示中,你會需要它們,此外你還可以將它們上傳到你指定的Git倉庫中。


Docker File


<code>
FROM python:3

RUN pip install flask

RUN mkdir -p /corp/app
WORKDIR /corp/app
COPY main.py .
ENV FLASK_APP=/corp/app/main.py

ENV APP_NAME=MyApp.DevOps
ENV APP_VERSION=v1.0.0

CMD ["flask", "run", "--host=127.0.0.1"]/<code>


main.py Python 腳本文件


<code>
import os
from flask import Flask
app = Flask(__name__)

@app.route('/')
def index():
appname = os.environ['APP_NAME']
appversion = os.environ['APP_VERSION']

response = "%s - %s.%s\\n" %('Hello World', appname, appversion)
return response/<code>


Kubernetes Deployment文件


<code>
apiVersion: v1
kind: Namespace
metadata:
name: my-demo
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: fluxdemo
namespace: my-demo
annotations:
flux.weave.works/tag.flask: glob:develop-v*
flux.weave.works/automated: 'true'
labels:
role: fluxdemo
env: demo
app: flux
spec:
replicas: 1
selector:
matchLabels:
role: fluxdemo
template:
metadata:
labels:

role: fluxdemo
spec:
containers:
- name: nginx
image: nginx:1.16-perl
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 80
volumeMounts:
- name: nginx-proxy-config
mountPath: /etc/nginx/conf.d/default.conf
subPath: nginx.conf
- name: flask
image: docker.io/<your>/flaskapp:develop-v1.8.0
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 5000
env:
- name: APP_NAME
value: myfluxdemo.K8s.GitOps
- name: APP_VERSION
value: v1.0.5
volumes:
- name: nginx-proxy-config
configMap:
name: nginx-conf
---
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-conf
namespace: my-demo
data:
nginx.conf: |-
#CODE1.0:
#add the nginx.conf configuration - this will be referenced within the deployment.yaml
server {
listen 80;
server_name localhost;

location / {
proxy_pass http://localhost:5000/;
proxy_set_header Host "localhost";
}
}/<your>/<code>


安裝Flux


  • 安裝Fluxctlhttps://docs.fluxcd.io/en/1.18.0/references/fluxctl.html
  • 安裝Fluxcdhttps://docs.fluxcd.io/en/1.18.0/tutorials/get-started.html


為Repo配置Flux


創建一個命名空間


<code>
kubectl create ns <namespace>
export FLUX_FORWARD_NAMESPACE= <namespace>
fluxctl list-workloads/<namespace>/<namespace>/<code>


安裝Fluxcd以建立與你的Git Repo的連接


<code>
export GHUSER=""

export REPO="gitops-demo"
export NS="flux"
fluxctl install \\
--git-user=${GHUSER} \\
--git-email=${GHUSER}@users.noreply.github.com \\
[email protected]:
Image download failed.
{REPO} \\
--namespace=${NS} | kubectl apply -f -/<code>


創建SSH密鑰以添加到Github倉庫


在你的terminal中輸入以下命令,以獲取下一步所需的密鑰:

<code>
fluxctl identity/<code>

打開Github,導航到安裝Fluxcd時添加的倉庫,轉到設置-部署密鑰,單擊【添加部署密鑰】,為其指定title,選中【允許write access】,粘貼公共密鑰,然後單擊【添加密鑰】。


在Git Repo中升級Deployment Manifest


打開你的Git Repo,裡面應該有deployment.yaml文件,向下滑動直到如下所示部分,然後更改APP_VERSION號碼

<code>
kubectl get pods -n copy the pod name kubectl port-forward 8080:80 -n
/<code>

保存並Commit更改到你的Repo。


Flux將在5分鐘之內升級你的deployment

要從localhost進行測試,請在Kubernetes中使用“Port-forward”命令:

<code>
kubectl get pods -n copy the pod name kubectl port-forward 8080:80 -n
/<code>

打開其他terminal:

<code>
response = "%s - %s.%s\\n" %('Flux World', appname, appversion)/<code>

升級容器鏡像並同步


現在讓我們對Docker鏡像進行修改並將其上傳到我們的Docker Hub鏡像倉庫中。為此,我們將修改flaskapp目錄中的main.py文件。


升級main.py文件。將Hello World更改為其他內容

<code>
response = "%s - %s.%s\\n" %('Flux World', appname, appversion)/<code>

創建一個新的Docker文件並上傳到Docker(以及另一個增量版本號)。


等待5分鐘,Flux將會自動部署新鏡像


配置漂移並同步


現在,我們來測試一下手動更改正在運行的配置會發生什麼。


<code>kubectl scale deployment/fluxdemo --replicas=4 -n/<code>

現在,我們花幾分鐘來看看pod並觀察發生了什麼。我們將會在短時間內(5分鐘以內)看到其他的pod,此外我們還將看到許多pod終止。因此,Flux已使配置恢復到當前在Git中保留的已聲明的部署狀態。

<code>
kubectl get po -n --watch/<code>

重新運行相同的命令,並且你會看到目前僅有一個正在運行的pod。


別忘了清理和移除deployment和Git連接(如果你想移除它)。否則,你需要開始添加更多的倉庫並繼續進行構建。


總 結


本文中我們簡單介紹了GitOps概念、它與CI/CD的關係以及它對應用程序的生命週期的改變。最後我們還demo了GitOps中的一個小工具Flux,它可以幫助把Kubernetes和Git集成起來,從而優化CI/CD流程。


本文僅僅是一個GitOps的引子,希望你可以通過它更好地入門GitOps,進而提升你的開發部署體驗。


分享到:


相關文章: