GitOps实战

简介

GitOps是一种开发运维实践,其核心思想是将整个应用环境以文件形式保存在Git仓库中,并通过Git的相关工具对应用进行更新、回滚等操作。

OneDev(https://github.com/theonedev/onedev)是一个开源的自带持续集成和部署功能的Git仓库管理软件,和GitLab类似,但更简单,机器要求低,性能好。

这篇文章介绍使用OneDev对基于Kubernetes的应用实现GitOps。

创建Kubernetes集群

首先我们需要一个Kubernetes集群,您可以使用现成的,也可以新建一个。这里我们使用阿里云的ACK。登录到阿里云ACK控制台,并创建费用较低的ACK托管版集群。相关选项:

  1. 集群规格:选择较便宜的标准版即可
  2. 配置SNAT:必须勾选
  3. 公网访问:必须勾选
  4. Worker配置:两个节点即可。每个节点内存至少为4G。使用默认操作系统。登录方式为简单起见选择密码并设置
  5. 组件配置:除了勾选“安装Ingress组件“,其余组件均不需要

集群创建成功后,将连接信息里的公网访问凭据复制到本地文件$HOME/.kube/config并运行如下命令确认能够连接到集群(如果本地还没有kubectl,可以参照此文先进行安装):

$ kubectl cluster-info 

由于国内访问官方Docker Registry太慢,我们还需要使用阿里的容器镜像服务。访问容器镜像服务,并在合适的命名空间内创建镜像仓库gitops-demo。为方便配置,仓库类型选择公开。代码源选择本地仓库。镜像仓库创建后,详情页里查看所在阿里云区域的docker registry(比如http://registry.cn-shanghai.aliyuncs.com),并确保在命令行里能用合适的用户名和密码登录该registry。

部署OneDev

为方便对集群里的应用进行控制,我们将OneDev部署到Kubernetes集群里。

1.运行下面的命令设置默认的storageclass。因为OneDev的部署需要申请储存卷(详见下步):

kubectl patch storageclass alicloud-disk-ssd -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'

2.下载OneDev的K8s资源定义, 解压并运行如下命令(OneDev部署会创建两个存储卷:100G的用来存储Git仓库,20G的用来存储MySQL数据库,存储卷的大小可以在文件k8s-resources/production/disk-settings.yaml中进行修改):

$ cd k8s-resources/production
$ kubectl apply -k .

3.部署完成后,运行下面的命令获取OneDev服务的external ip(如果external ip还未分配,等待片刻后再重试):

$ kubectl get services -n onedev

4.在浏览器内访问地址http://<OneDev external ip>并按提示配置OneDev(除了创建管理员账号外,其余均用默认设置)。如果网页无法访问,等待片刻再重试。

创建示例应用

接着我们配置一个示例应用:

1.在OneDev Projects页面中创建一个名为gitops-demo的项目
2.在命令行下运行如下命令创建一个react项目并push到OneDev(该步骤需要node.js运行环境,具体参照react文档:

$ npx create-react-app gitops-demo 
$ cd gitops-demo
$ git remote add origin http://<OneDev external ip>/gitops-demo
$ git push --set-upstream origin master 
(使用之前创建的OneDev管理员作为push的账号)

3.刷新OneDev示例项目的Files页面,并按下图所示点击Add build spec链接:

2020-12-16_08-54-11.png

4.在build spec编辑页面中,点击Edit Source(注意之前不要增加任何Job),然后将build spec的源代码替换为如下内容:

version: 1
jobs:
- name: CI
  image: node:15.4-alpine
  commands:
  - set -e
  - ''
  - apk add --update jq
  - buildVersion=`jq -r '.version' package.json`
  - echo "##onedev[SetBuildVersion '$buildVersion']"
  - ''
  - yarn install
  - ''
  - export CI=true
  - yarn test
  triggers:
  - !BranchUpdateTrigger {}
  retrieveSource: true
  cloneCredential: !DefaultCredential {}
  cpuRequirement: 250m
  memoryRequirement: 128m
  retryCondition: never
  maxRetries: 3
  retryDelay: 30
  caches:
  - key: npm-cache
    path: /root/.npm
  timeout: 3600

5.保存并提交改动。如下图所示,OneDev将自动对示例项目进行构建:

2020-12-16_09-15-37.png

实施GitOps

我们已经能够构建示例应用,下面着手将它部署到Kubernetes中:

1.要部署到Kubernetes中,我们首先需要构建示例应用的docker image。在示例项目的根目录创建文件Dockerfile,内容如下:

FROM nginx:1.19.5 
COPY build /usr/share/nginx/html 
EXPOSE 80

文件提交后OneDev会自动构建,这时不必理会。

2.继续在根目录创建用来描述部署的Kubernetes资源文件k8s.yaml。内容如下。注意需要将<docker repository>替换为容器仓库的地址,比如registry.cn-shanghai.aliyuncs.com/test/gitops-demo,具体地址在前述阿里云容器镜像仓库的详情页里有显示。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: gitops-demo
  labels:
    tier: gitops-demo
spec:
  selector:
    matchLabels:
      tier: gitops-demo
  strategy:
    type: Recreate
  template:
    metadata:
      name: gitops-demo
      labels:
        tier: gitops-demo
    spec:
      containers:
      - name: gitops-demo
        image: <docker repository>:imageTag
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: gitops-demo
  labels:
    tier: gitops-demo
spec:
  type: LoadBalancer
  ports:
  - name: http
    port: 80
    targetPort: 80
    protocol: TCP
  selector:
    tier: gitops-demo

3.为了能够将示例应用的image发布到阿里云的docker registry,OneDev需要知道docker registry的密码。在示例项目里增加一个job secret,给它一个名字,比如docker-registry-password,并将值设置为docker registry的访问密码。如下图所示:

2020-12-16_10-31-39.png

4.因为需要在构建时将示例应用部署到Kubernetes,OneDev需要额外的集群权限。在本机创建文件gitops-demo-role.yaml并包含如下内容:

kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: gitops-demo
rules:
- apiGroups: [""]
  resources: ["services"]
  verbs: ["get", "create"]
- apiGroups: ["apps"]
  resources: ["deployments"]
  verbs: ["get", "patch", "create"]

然后在命令行下运行如下命令:

$ kubectl apply -f gitops-demo-role.yaml

接着在OneDev的管理页面里删除原有的auto-discover job executor,并新建一个Kubernetes Executor。设置名字,并将字段Cluster Role设置为gitops-demo。其他内容保持不变,然后保存。具体如下所示:

2020-12-16_11-05-06.png

5.最后在OneDev里回到示例项目页面,在文件根目录中点击.onedev-buildspec.yml查看详情,然后进行编辑。将image字段设置为docker:19.03.5,并将commands字段设置为如下内容。注意需要将<docker-registry-login>替换为前述阿里云docker registry的登录名,将<docker repository>替换为容器仓库的地址(例如registry.cn-shanghai.aliyuncs.com/test/gitops-demo),以及将<docker registry>替换为所在阿里云区域的docker registry(例如registry.cn-shanghai.aliyuncs.com)。这些属性均可在前述容器镜像仓库的详情内查看。

set -e
apk add --update npm jq curl
buildVersion=`jq -r '.version' package.json`
echo "##onedev[SetBuildVersion '$buildVersion']"

npm install -g yarn
yarn install
export CI=true
yarn test
yarn build

docker build -t <docker repository>:@commit_hash@ .

docker login -u <docker-registry-login> -p @secrets:docker-registry-password@ <docker registry>

docker push <docker repository>:@commit_hash@

curl -o /usr/local/bin/kubectl -LO "https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl"

chmod +x /usr/local/bin/kubectl
sed -i "s/imageTag/@commit_hash@/g" k8s.yaml
kubectl apply -f k8s.yaml -n default

6.保存并提交改动。OneDev就会开始构建并部署示例应用。构建成功后,运行下面的命令查看示例应用的external ip:

kubectl get service gitops-demo

然后就可以用浏览器打开地址http://<gitops-demo-external-ip-address>来访问部署好的示例应用了。

恭喜!现在您已经成功配置了一个简单的GitOps流程:当有新的commit提交到主分支时(无论是通过push还是通过pull request合并),OneDev的CI任务会自动触发来构建、测试并重新部署示例项目。当需要回滚到前一个部署时,只需要运行git revert master命令,并将改动提交到主分支即可。

管理多个部署环境

在上面的部署中,我们将示例应用直接部署到了集群的默认名字空间中。在实际项目中,我们可能需要创建多个名字空间来对应多个部署环境。下面我们创建productiontest名字空间,分别对应我们的生产和测试环境:

$ kubectl create namespace test
$ kubectl create namespace production

编辑build spec将Commands字段的最后一行替换为如下内容:

if [ "@branch@" = "master" ]; then 
    kubectl apply -f k8s.yaml -n production
else
    kubectl apply -f k8s.yaml -n @branch@ 
fi;

这告诉OneDev将所有提交到主分支的改动部署到生产环境,并将其他分支的改动部署到和分支名相同的命名空间中。

改动提交到主分支后,示例应用将会被部署到生产环境中。接着我们在OneDev里创建test分支,可以看到该分支创建后,示例应用也被部署到测试环境中。

2020-12-19_11-06-46.png

可以在命令行下运行如下命令查看特定部署环境的external ip。注意需要将<namespace>替换为对应环境的集群名字空间:

kubectl get service -n <namespace>

这样在OneDev的commits页面里,我们就可以一目了然的查看和控制各个环境的部署情况了。

2020-12-16_15-53-35.png

感谢阅读!

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,686评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,668评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,160评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,736评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,847评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,043评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,129评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,872评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,318评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,645评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,777评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,470评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,126评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,861评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,095评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,589评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,687评论 2 351

推荐阅读更多精彩内容

  • 目录 Docker简介 Docker优势 Docker基本概念 Docker安装使用 Docker常用命令 Doc...
    喔喔松阅读 348评论 0 0
  • Docker简介 Docker是一个开源的应用容器引擎,开发者可以打包自己的应用到容器里面,然后迁移到其他机器的d...
    程序员知识圈阅读 5,719评论 7 156
  • 久违的晴天,家长会。 家长大会开好到教室时,离放学已经没多少时间了。班主任说已经安排了三个家长分享经验。 放学铃声...
    飘雪儿5阅读 7,515评论 16 22
  • 今天感恩节哎,感谢一直在我身边的亲朋好友。感恩相遇!感恩不离不弃。 中午开了第一次的党会,身份的转变要...
    迷月闪星情阅读 10,559评论 0 11
  • 可爱进取,孤独成精。努力飞翔,天堂翱翔。战争美好,孤独进取。胆大飞翔,成就辉煌。努力进取,遥望,和谐家园。可爱游走...
    赵原野阅读 2,723评论 1 1