跳到主要内容

6 篇博文 含有标签「CICD」

查看所有标签

Argo Rollout 管理

· 阅读需 7 分钟

安装 argo rollouts

kubectl create namespace argo-rollouts
kubectl apply -n argo-rollouts -f https://github.com/argoproj/argo-rollouts/releases/download/v1.2.2/install.yaml

# 验证
kubectl get pods -n argo-rollouts

安装插件

# https://github.91chi.fun/https://github.com//argoproj/argo-rollouts/releases/download/v1.2.2/kubectl-argo-rollouts-linux-amd64

curl -LO https://github.com/argoproj/argo-rollouts/releases/download/v1.2.2/kubectl-argo-rollouts-linux-amd64

# 赋予权限
chmod +x ./kubectl-argo-rollouts-linux-amd64

# 将该二进制文件移动到对应路径
mv ./kubectl-argo-rollouts-linux-amd64 /usr/local/bin/kubectl-argo-rollouts

# 验证
kubectl argo rollouts version

使用 Rollout

部署 Rollout

首先部署一个 Rollout 资源和一个针对该资源的 Kubernetes Service 对象,这里我们示例中的 Rollout 采用了金丝雀的更新策略,将 20% 的流量发送到金丝雀上,然后手动发布,最后在升级的剩余时间内逐渐自动增大流量,可以通过如下所示的 Rollout 来描述这个策略:

# basic-rollout.yaml
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: rollouts-demo
spec:
replicas: 5 # 定义5个副本
strategy: # 定义升级策略
canary: # 金丝雀发布
steps: # 发布的节奏
- setWeight: 20
- pause: {} # 会一直暂停
- setWeight: 40
- pause: { duration: 10 } # 暂停10s
- setWeight: 60
- pause: { duration: 10 }
- setWeight: 80
- pause: { duration: 10 }
revisionHistoryLimit: 2 # 下面部分其实是和 Deployment 兼容的
selector:
matchLabels:
app: rollouts-demo
template:
metadata:
labels:
app: rollouts-demo
spec:
containers:
- name: rollouts-demo
image: argoproj/rollouts-demo:blue
ports:
- name: http
containerPort: 8080
protocol: TCP
resources:
requests:
memory: 32Mi
cpu: 5m

还包括一个如下所示的 Service 资源对象:

# basic-service.yaml
apiVersion: v1
kind: Service
metadata:
name: rollouts-demo
spec:
ports:
- port: 80
targetPort: http
protocol: TCP
name: http
selector:
app: rollouts-demo

直接创建上面的两个资源对象:

kubectl apply -f basic-rollout.yaml
kubectl apply -f basic-service.yaml

任何 Rollout 的初始创建都会立即将副本扩展到 100%(跳过任何金丝雀升级步骤、分析等...),因为还没有发生升级。

$ kubectl get pods -l app=rollouts-demo
NAME READY STATUS RESTARTS AGE
rollouts-demo-687d76d795-6ppnh 1/1 Running 0 53s
rollouts-demo-687d76d795-8swrk 1/1 Running 0 53s
rollouts-demo-687d76d795-fnt2w 1/1 Running 0 53s
rollouts-demo-687d76d795-mtvtw 1/1 Running 0 53s
rollouts-demo-687d76d795-sh56l 1/1 Running 0 53s

Argo Rollouts 的 kubectl 插件允许我们可视化 Rollout 以及相关资源对象,并展示实时状态变化,要在部署过程中观察 Rollout,可以通过运行插件的 get rollout --watch 命令,比如:

kubectl argo rollouts get rollout rollouts-demo --watch

更新 Rollout

上面已经部署完成,接下来就需要执行更新了,和 Deployment 类似,对 Pod 模板字段的任何变更都会导致新的版本(即 ReplicaSet)被部署,更新 Rollout 通常是修改容器镜像的版本,然后执行 kubectl apply ,为了方便,rollouts 插件还单独提供了一个 set image 的命令,比如这里我们运行以下所示命令,用 yellow 版本的容器更新上面的 Rollout:

$ kubectl argo rollouts set image rollouts-demo \
rollouts-demo=argoproj/rollouts-demo:yellow

rollout "rollouts-demo" image updated

在 rollout 更新期间,控制器将通过 Rollout 更新策略中定义的步骤进行。这个示例的 rollout 为金丝雀设置了 20% 的流量权重,并一直暂停 rollout,直到用户取消或促进发布。在更新镜像后,再次观察 rollout,直到它达到暂停状态。

$ kubectl argo rollouts get rollout rollouts-demo --watch

当 demo rollout 到达第二步时,我们可以从插件中看到,Rollout 处于暂停状态,现在有 5 个副本中的 1 个运行新版本的 pod,其余 4 个仍然运行旧版本,这相当于 setWeight: 20 步骤所定义的 20%的金丝雀权重。

Promote Rollout

经过上面的更新后,Rollout 现在处于暂停状态,当一个 Rollout 到达一个没有持续时间的暂停步骤时,它将一直保持在暂停状态,直到它被恢复/提升。要手动将 Rollout 切换到下一个步骤,请运行插件的 promotion 命令。

$ kubectl argo rollouts promote rollouts-demo

rollout 'rollouts-demo' promoted

切换后 Rollout 将继续执行剩余的步骤。在我们的例子中,剩余的步骤是完全自动化的,所以 Rollout 最终会完成步骤,直到它已经完全过渡到新版本。再次观察 Rollout,直到它完成所有步骤。

$ kubectl argo rollouts get rollout rollouts-demo --watch

promote 命令还支持用 --full 标志跳过所有剩余步骤和分析。

可以看到 stable 版本已经切换到 revision:2 这个 ReplicaSet 了。在更新过程中,无论何时,无论是通过失败的金丝雀分析自动中止,还是由用户手动中止,Rollout 都会退回到 stable 版本。

中断 Rollout

如何在更新过程中手动中止 Rollout,首先,使用 set image 命令部署一个新的 red 版本的容器,并等待 rollout 再次达到暂停的步骤。

$ kubectl argo rollouts set image rollouts-demo \
rollouts-demo=argoproj/rollouts-demo:red

rollout "rollouts-demo" image updated

这一次中止更新,而不是将滚动切换到下一步,这样它就回到了 stable 版本,该插件同样提供了一个 abort 命令,可以在更新过程中的任何时候手动中止 Rollout。

$ kubectl argo rollouts abort rollouts-demo

当中止滚动时,它将扩大 ReplicaSet 的 stable 版本(在本例中是 yellow 版本),并缩小任何其他版本。尽管 ReplicaSet 的稳定版本可能正在运行,并且是健康的,但整个 Rollout 仍然被认为是退化的,因为期望的版本(red 版本)不是实际运行的版本。

$ kubectl argo rollouts get rollout rollouts-demo --watch

为了使 Rollout 再次被认为是健康的而不是有问题的版本,有必要将所需的状态改回以前的稳定版本。在我们的例子中,我们可以简单地使用之前的 yellow 镜像重新运行 set image 命令即可。

$ kubectl argo rollouts set image rollouts-demo \
rollouts-demo=argoproj/rollouts-demo:yellow

运行这个命令后,可以看到 Rollout 立即变成了 health 状态,而且没有任何关于创建新 ReplicaSets 的动态。

$ kubectl argo rollouts get rollout rollouts-demo --watch

当 Rollout 还没有达到预期状态(例如,它被中止了,或者正在更新中),而稳定版本的资源清单被重新应用,Rollout 检测到这是一个回滚,而不是一个更新,并将通过跳过分析和步骤快速部署稳定的 ReplicaSet。

上面例子中的 Rollout 没有使用 Ingress 控制器或服务网格来控制流量。相反,它使用正常的 Kubernetes Service 来实现近似的金丝雀权重,基于新旧副本数量的比例来实现。所以,这个 Rollout 有一个限制,即它只能实现 20% 的最小加权,通过扩展 5 个 pod 中的一个来运行新版本。为了实现更细粒度的金丝雀,这就需要一个 Ingress 控制器或服务网格了。

Dashboard

Argo Rollouts Kubectl 插件可以提供一个本地 Dashboard,来可视化你的 Rollouts。

要启动这个 Dashboard,需要在包含 Rollouts 资源对象的命名空间中运行 kubectl argo rollouts dashboard 命令,然后访问localhost:3100 即可

点击 Rollout 可以进行详细页面,在详细页面可以看到 Rollout 的配置信息,还可以直接在 UI 界面上执行一些常用的操作,比如重启、重启、中断等。

ArgoCD 构建

· 阅读需 3 分钟

安装 argoCD

快速搭建

kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/v2.4.9/manifests/install.yaml

高可用搭建

kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/v2.4.9/manifests/ha/install.yaml

此刻 Argo CD 的服务和应用资源都将部署到该命名空间

$ kubectl get pods -n argocd
NAME READY STATUS RESTARTS AGE
argocd-application-controller-0 1/1 Running 0 103s
argocd-applicationset-controller-68b9bdbd8b-jzcpf 1/1 Running 0 103s
argocd-dex-server-6b7745757-6mxwk 1/1 Running 0 103s
argocd-notifications-controller-5b56f6f7bb-jqpng 1/1 Running 0 103s
argocd-redis-f4cdbff57-dr8jc 1/1 Running 0 103s
argocd-repo-server-c4f79b4d6-7nh6n 1/1 Running 0 103s
argocd-server-895675597-fr42g 1/1 Running 0 103s

如果对 UI、SSO、多集群管理这些特性不感兴趣,只想把应用变更同步到集群中,那么你可以使用 --disable-auth 标志来禁用认证,可以通过命令 kubectl patch deploy argocd-server -n argocd -p '[{"op": "add", "path": "/spec/template/spec/containers/0/command/-", "value": "--disable-auth"}]' --type json 来实现。

安装 argoCD 客户端

# 此命令是将 VERSION 改为 argoCD 的最新版本
VERSION=$(curl --silent "https://api.github.com/repos/argoproj/argo-cd/releases/latest" | grep '"tag_name"' | sed -E 's/.*"([^"]+)".*/\1/')

# 客户端和服务端版本要匹配,此处 $VERSION 可以改为 v2.4.9,跟我们的服务端对应
curl -sSL -o /usr/local/bin/argocd https://github.com/argoproj/argo-cd/releases/download/$VERSION/argocd-linux-amd64

修改 svc 的 type

kubectl edit -n argocd svc argocd-server

# 改为 NodePort 类型
type: NodePort

# 改为你要的 Port
ports:
- name: http
nodePort: 32555 #固定端口,可用内网 nginx 再做一层反向代理统一管理。(ingress也可以)
port: 80
protocol: TCP
targetPort: 8080
- name: https
nodePort: 31000
port: 443
protocol: TCP
targetPort: 8080

查看登陆密码

kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d && echo

# 访问 argoCD web UI 登陆,IP+Port
# 账号密码:
admin
MgCxQhhvtEULEmJ7

客户端登陆

argocd  login IP:32555
WARNING: server certificate had error: x509: cannot validate certificate for 8.222.173.77 because it doesn't contain any IP SANs. Proceed insecurely (y/n)? y
Username: admin
Password:
'admin:login' logged in successfully
Context '8.222.173.77:32555' updated

# 输入账号密码即可,error: x509直接 y 确认。

配置集群

由于 Argo CD 支持部署应用到多集群,所以如果你要将应用部署到外部集群的时候,需要先将外部集群的认证信息注册到 Argo CD 中,如果是在内部部署(运行 Argo CD 的同一个集群,默认不需要配置),直接使用 https://kubernetes.default.svc 作为应用的 K8S APIServer 地址即可。

# 首先列出当前 kubeconfig 中的所有集群上下文:
$ kubectl config get-contexts -o name

# 从列表中选择一个上下文名称并将其提供给 argocd cluster add CONTEXTNAME,比如对于 kind-kind上下文,运行:
$ argocd cluster add kubernetes-admin@kubernetes

FluxCD 搭建测试

· 阅读需 3 分钟

安装 FluxCD

# 集群内安装 FluxCD
kubectl apply -f https://ghproxy.com/https://raw.githubusercontent.com/lyzhang1999/resource/main/fluxcd/fluxcd.yaml

# 安装 FluxCD 的工作负载比较多,你也使用 kubectl wait 来等待安装完成
kubectl wait --for=condition=available --timeout=300s --all deployments -n flux-systemdeployment.apps/helm-controller condition metdeployment.apps/image-automation-controller condition metdeployment.apps/image-reflector-controller condition metdeployment.apps/kustomize-controller condition metdeployment.apps/notification-controller condition metdeployment.apps/source-controller condition met

# 本地创建 fluxcd-demo 目录
mkdir fluxcd-demo && cd fluxcd-demo

在 fluxcd-demo 目录下创建 deployment.yaml 文件,并将下面的内容保存到这个文件里

apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: hello-world-flask
name: hello-world-flask
spec:
replicas: 2
selector:
matchLabels:
app: hello-world-flask
template:
metadata:
labels:
app: hello-world-flask
spec:
containers:
- image: lyzhang1999/hello-world-flask:latest
name: hello-world-flask

将此 yaml 推入 github/gitlab 仓库中

配置FluxCD与仓库连接信息

编辑 fluxcd-repo.yaml ,此内容为创建仓库连接信息

apiVersion: source.toolkit.fluxcd.io/v1beta2
kind: GitRepository
metadata:
name: hello-world-flask
spec:
interval: 5s
ref:
branch: main
url: https://github.com/lyzhang1999/fluxcd-demo

使用 kubectl apply 将其 GitRepository 对象部署到集群内

kubectl apply -f fluxcd-repo.yaml
gitrepository.source.toolkit.fluxcd.io/hello-world-flask created

# 验证
kubectl get gitrepository

创建部署策略

编辑 fluxcd-kustomize.yaml ,为 FluxCD 创建部署策略

apiVersion: kustomize.toolkit.fluxcd.io/v1beta2
kind: Kustomization
metadata:
name: hello-world-flask
spec:
interval: 5s
path: ./
prune: true
sourceRef:
kind: GitRepository
name: hello-world-flask
targetNamespace: default

将 kustomization 对象部署到集群内:

kubectl apply -f  fluxcd-kustomize.yaml 

# 验证
kubectl get kustomization

自动发布

修改 fluxcd-demo 仓库的 deployment.yaml 文件

 - image: lyzhang1999/hello-world-flask:v1 # 修改此处  

# 将修改推送到远端仓库
git add -A && git commit -m "Update image tag to v1"
git push origin main

# 可以使用 kubectl describe kustomization hello-world-flask 查看触发重新部署的事件
kubectl describe kustomization hello-world-flask

# 通过上面的配置,让 FluxCD 自动完成了监听修改、比较和重新部署

发布回滚

GitOps 工作流中,Git 仓库是描述期望状态的唯一可信源,那么只要对 Git 仓库执行回滚,就可以实现发布回滚

# 回滚 fluxcd-demo 仓库,可以使用 git log 来查看它
git log

# 可以看到,上一次的 commit id 为 75f39dc58101b2406d4aaacf276e4d7b2d429fc9,接下来使用 git reset 来回滚到上一次提交,并强制推送到 Git 仓库
git reset --hard 75f39dc58101b2406d4aaacf276e4d7b2d429fc9

# 使用 kubectl describe kustomization hello-world-flask 查看触发重新部署的事件
kubectl describe kustomization hello-world-flask

# 从返回结果的 Last Applied Revision 可以看出,FluxCD 已经检查到了变更,并已经进行了同步。