CD 被认为是一种企业软件实践,是既定 CI 原则自然演变的结果。 然而,CD 仍然很少见,这可能是由于管理的复杂性以及担心部署失败会影响系统可用性。
以下是在 Google Kubernetes Engine (GKE) 上设置和使用 Flagger 的分步指南。
设置 Kubernetes 集群
您首先使用 Istio 附加组件创建一个 GKE 集群(如果您没有 GCP 帐户,您可以注册
登录 Google Cloud,创建项目,并为其启用计费。 安装命令行实用程序 gcloud init
.
设置默认项目、计算区域和区域(替换 PROJECT_ID
为您的项目):
gcloud config set project PROJECT_ID
gcloud config set compute/region us-central1
gcloud config set compute/zone us-central1-a
启用 GKE 服务并使用 HPA 和 Istio 附加组件创建集群:
gcloud services enable container.googleapis.com
K8S_VERSION=$(gcloud beta container get-server-config --format=json | jq -r '.validMasterVersions[0]')
gcloud beta container clusters create istio
--cluster-version=${K8S_VERSION}
--zone=us-central1-a
--num-nodes=2
--machine-type=n1-standard-2
--disk-size=30
--enable-autorepair
--no-enable-cloud-logging
--no-enable-cloud-monitoring
--addons=HorizontalPodAutoscaling,Istio
--istio-config=auth=MTLS_PERMISSIVE
上面的命令将创建一个包含两个虚拟机的默认节点池 n1-standard-2
(vCPU:2,RAM 7,5 GB,磁盘:30 GB)。 理想情况下,您应该将 Istio 组件与您的工作负载隔离开来,但是没有简单的方法可以在专用节点池中运行 Istio Pod。 Istio 清单被认为是只读的,GKE 将撤消任何更改,例如链接到节点或从 pod 分离。
设置凭据 kubectl
:
gcloud container clusters get-credentials istio
创建集群管理员角色绑定:
kubectl create clusterrolebinding "cluster-admin-$(whoami)"
--clusterrole=cluster-admin
--user="$(gcloud config get-value core/account)"
安装命令行工具
brew install kubernetes-helm
Homebrew 2.0 现在也可用于
为 Tiller 创建服务账户和集群角色绑定:
kubectl -n kube-system create sa tiller &&
kubectl create clusterrolebinding tiller-cluster-rule
--clusterrole=cluster-admin
--serviceaccount=kube-system:tiller
在命名空间中展开 Tiller kube-system
:
helm init --service-account tiller
您应该考虑在 Helm 和 Tiller 之间使用 SSL。 有关保护 Helm 安装的更多信息,请参阅
确认设置:
kubectl -n istio-system get svc
几秒钟后,GCP 应该为该服务分配一个外部 IP 地址 istio-ingressgateway
.
配置 Istio 入口网关
使用名称创建静态 IP 地址 istio-gateway
使用 Istio 网关的 IP 地址:
export GATEWAY_IP=$(kubectl -n istio-system get svc/istio-ingressgateway -ojson | jq -r .status.loadBalancer.ingress[0].ip)
gcloud compute addresses create istio-gateway --addresses ${GATEWAY_IP} --region us-central1
现在您需要一个 Internet 域并访问您的 DNS 注册商。 添加两条A记录(替换 example.com
到您的域):
istio.example.com A ${GATEWAY_IP}
*.istio.example.com A ${GATEWAY_IP}
验证 DNS 通配符是否正常工作:
watch host test.istio.example.com
创建一个通用 Istio 网关以通过 HTTP 在服务网格外部提供服务:
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: public-gateway
namespace: istio-system
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "*"
将上述资源保存为 public-gateway.yaml 然后应用它:
kubectl apply -f ./public-gateway.yaml
任何生产系统都不应在没有 SSL 的情况下在 Internet 上提供服务。 要使用证书管理器、CloudDNS 和 Let's Encrypt 保护 Istio 入口网关,请阅读
标记器安装
GKE Istio 附加组件不包含清理 Istio 遥测服务的 Prometheus 实例。 因为 Flagger 使用 Istio HTTP 指标来执行金丝雀分析,所以您需要部署以下 Prometheus 配置,类似于官方 Istio Helm 模式附带的配置。
REPO=https://raw.githubusercontent.com/stefanprodan/flagger/master
kubectl apply -f ${REPO}/artifacts/gke/istio-prometheus.yaml
添加 Flagger Helm 存储库:
helm repo add flagger [https://flagger.app](https://flagger.app/)
将 Flagger 扩展到命名空间 istio-system
通过启用 Slack 通知:
helm upgrade -i flagger flagger/flagger
--namespace=istio-system
--set metricsServer=http://prometheus.istio-system:9090
--set slack.url=https://hooks.slack.com/services/YOUR-WEBHOOK-ID
--set slack.channel=general
--set slack.user=flagger
您可以在任何命名空间中安装 Flagger,只要它可以与端口 9090 上的 Istio Prometheus 服务通信即可。
Flagger 有一个用于金丝雀分析的 Grafana 仪表板。 在命名空间中安装 Grafana istio-system
:
helm upgrade -i flagger-grafana flagger/grafana
--namespace=istio-system
--set url=http://prometheus.istio-system:9090
--set user=admin
--set password=change-me
通过创建虚拟服务(替换 example.com
到您的域):
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: grafana
namespace: istio-system
spec:
hosts:
- "grafana.istio.example.com"
gateways:
- public-gateway.istio-system.svc.cluster.local
http:
- route:
- destination:
host: flagger-grafana
将上面的资源保存为grafana-virtual-service.yaml 然后应用:
kubectl apply -f ./grafana-virtual-service.yaml
当移动到 http://grafana.istio.example.com
在浏览器中,您应该被定向到 Grafana 登录页面。
使用 Flagger 部署 Web 应用程序
Flagger 部署 Kubernetes 并可选择自动横向扩展 (HPA),然后创建一系列对象(Kubernetes 部署、ClusterIP 服务和 Istio 虚拟服务)。 这些对象将应用程序暴露给服务网格并控制金丝雀分析和进度。
创建启用 Istio Sidecar 注入的测试命名空间:
REPO=https://raw.githubusercontent.com/stefanprodan/flagger/master
kubectl apply -f ${REPO}/artifacts/namespaces/test.yaml
创建 deployment 和 pod 自动扩容工具:
kubectl apply -f ${REPO}/artifacts/canaries/deployment.yaml
kubectl apply -f ${REPO}/artifacts/canaries/hpa.yaml
部署测试负载服务以在金丝雀分析期间生成流量:
helm upgrade -i flagger-loadtester flagger/loadtester
--namepace=test
创建自定义金丝雀资源(替换 example.com
到您的域):
apiVersion: flagger.app/v1alpha3
kind: Canary
metadata:
name: podinfo
namespace: test
spec:
targetRef:
apiVersion: apps/v1
kind: Deployment
name: podinfo
progressDeadlineSeconds: 60
autoscalerRef:
apiVersion: autoscaling/v2beta1
kind: HorizontalPodAutoscaler
name: podinfo
service:
port: 9898
gateways:
- public-gateway.istio-system.svc.cluster.local
hosts:
- app.istio.example.com
canaryAnalysis:
interval: 30s
threshold: 10
maxWeight: 50
stepWeight: 5
metrics:
- name: istio_requests_total
threshold: 99
interval: 30s
- name: istio_request_duration_seconds_bucket
threshold: 500
interval: 30s
webhooks:
- name: load-test
url: http://flagger-loadtester.test/
timeout: 5s
metadata:
cmd: "hey -z 1m -q 10 -c 2 http://podinfo.test:9898/"
将上述资源保存为 podinfo-canary.yaml 然后应用它:
kubectl apply -f ./podinfo-canary.yaml
上述分析如果成功,将运行五分钟,每半分钟检查一次 HTTP 指标。 您可以使用以下公式确定验证和推广金丝雀部署所需的最短时间: interval * (maxWeight / stepWeight)
. 记录了 Canary CRD 字段
几秒钟后,Flagger 将创建金丝雀对象:
# applied
deployment.apps/podinfo
horizontalpodautoscaler.autoscaling/podinfo
canary.flagger.app/podinfo
# generated
deployment.apps/podinfo-primary
horizontalpodautoscaler.autoscaling/podinfo-primary
service/podinfo
service/podinfo-canary
service/podinfo-primary
virtualservice.networking.istio.io/podinfo
打开浏览器并转到 app.istio.example.com
, 你应该看到版本号
自动金丝雀分析和推广
Flagger 实现了一个控制循环,逐渐将流量转移到金丝雀,同时测量关键性能指标,例如 HTTP 请求成功率、平均请求持续时间和 pod 健康状况。 根据KPI分析,推进或中断金丝雀,并将分析结果发布到Slack。
当以下对象之一发生更改时,会触发金丝雀部署:
- 部署 PodSpec(容器镜像、命令、端口、环境等)
- ConfigMap 挂载为卷或映射到环境变量
- 秘密作为卷安装或转换为环境变量
更新容器镜像时运行 canary deploy:
kubectl -n test set image deployment/podinfo
podinfod=quay.io/stefanprodan/podinfo:1.4.1
Flagger 检测到部署版本已更改并开始解析它:
kubectl -n test describe canary/podinfo
Events:
New revision detected podinfo.test
Scaling up podinfo.test
Waiting for podinfo.test rollout to finish: 0 of 1 updated replicas are available
Advance podinfo.test canary weight 5
Advance podinfo.test canary weight 10
Advance podinfo.test canary weight 15
Advance podinfo.test canary weight 20
Advance podinfo.test canary weight 25
Advance podinfo.test canary weight 30
Advance podinfo.test canary weight 35
Advance podinfo.test canary weight 40
Advance podinfo.test canary weight 45
Advance podinfo.test canary weight 50
Copying podinfo.test template spec to podinfo-primary.test
Waiting for podinfo-primary.test rollout to finish: 1 of 2 updated replicas are available
Promotion completed! Scaling down podinfo.test
在分析期间,可以使用 Grafana 跟踪金丝雀结果:
请注意,如果在金丝雀分析期间将新更改应用于部署,则 Flagger 将重新启动分析阶段。
列出集群中的所有金丝雀:
watch kubectl get canaries --all-namespaces
NAMESPACE NAME STATUS WEIGHT LASTTRANSITIONTIME
test podinfo Progressing 15 2019-01-16T14:05:07Z
prod frontend Succeeded 0 2019-01-15T16:15:07Z
prod backend Failed 0 2019-01-14T17:05:07Z
如果您启用了 Slack 通知,您将收到以下消息:
自动回滚
在 Canary 分析期间,您可以生成合成 HTTP 500 错误和高响应延迟,以查看 Flagger 是否会停止部署。
创建一个测试 pod 并在其中执行以下操作:
kubectl -n test run tester
--image=quay.io/stefanprodan/podinfo:1.2.1
-- ./podinfo --port=9898
kubectl -n test exec -it tester-xx-xx sh
生成 HTTP 500 错误:
watch curl http://podinfo-canary:9898/status/500
延迟生成:
watch curl http://podinfo-canary:9898/delay/1
当失败的检查次数达到阈值时,流量被路由回主通道,金丝雀缩放为零,部署被标记为失败。
Canary 错误和延迟峰值被记录为 Kubernetes 事件,并由 Flagger 以 JSON 格式记录:
kubectl -n istio-system logs deployment/flagger -f | jq .msg
Starting canary deployment for podinfo.test
Advance podinfo.test canary weight 5
Advance podinfo.test canary weight 10
Advance podinfo.test canary weight 15
Halt podinfo.test advancement success rate 69.17% < 99%
Halt podinfo.test advancement success rate 61.39% < 99%
Halt podinfo.test advancement success rate 55.06% < 99%
Halt podinfo.test advancement success rate 47.00% < 99%
Halt podinfo.test advancement success rate 37.00% < 99%
Halt podinfo.test advancement request duration 1.515s > 500ms
Halt podinfo.test advancement request duration 1.600s > 500ms
Halt podinfo.test advancement request duration 1.915s > 500ms
Halt podinfo.test advancement request duration 2.050s > 500ms
Halt podinfo.test advancement request duration 2.515s > 500ms
Rolling back podinfo.test failed checks threshold reached 10
Canary failed! Scaling down podinfo.test
如果您启用了 Slack 通知,当超过截止日期或达到分析中失败检查的最大数量时,您将收到一条消息:
总之
除了 Kubernetes 之外,运行像 Istio 这样的服务网格将提供自动指标、日志和协议,但工作负载部署仍然依赖于外部工具。 Flagger 旨在通过添加 Istio 功能来改变这一点
Flagger 与任何 Kubernetes CI/CD 解决方案兼容,并且可以轻松扩展金丝雀分析
支持旗手
如果您有改进 Flagger 的建议,请在 GitHub 上提交问题或 PR
谢谢
来源: habr.com