简介
GitOps是一种开发运维实践,其核心思想是将整个应用环境以文件形式保存在Git仓库中,并通过Git的相关工具对应用进行更新、回滚等操作。
OneDev(https://github.com/theonedev/onedev)是一个开源的自带持续集成和部署功能的Git仓库管理软件,和GitLab类似,但更简单,机器要求低,性能好。
这篇文章介绍使用OneDev对基于Kubernetes的应用实现GitOps。
创建Kubernetes集群
首先我们需要一个Kubernetes集群,您可以使用现成的,也可以新建一个。这里我们使用阿里云的ACK。登录到阿里云ACK控制台,并创建费用较低的ACK托管版集群。相关选项:
- 集群规格:选择较便宜的标准版即可
- 配置SNAT:必须勾选
- 公网访问:必须勾选
- Worker配置:两个节点即可。每个节点内存至少为4G。使用默认操作系统。登录方式为简单起见选择密码并设置
- 组件配置:除了勾选“安装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.png4.在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.png4.因为需要在构建时将示例应用部署到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.png5.最后在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命令,并将改动提交到主分支即可。
管理多个部署环境
在上面的部署中,我们将示例应用直接部署到了集群的默认名字空间中。在实际项目中,我们可能需要创建多个名字空间来对应多个部署环境。下面我们创建production和test名字空间,分别对应我们的生产和测试环境:
$ 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感谢阅读!
网友评论