开始使用状态持久化
了解应用程序的状态持久化并创建一个集群。
如何持久化状态?
注意: 如果在重新调度过程中丢失了应用状态,那么容错性和高可用性将毫无意义。
拥有状态是不可避免的,无论我们的应用、服务器甚至整个数据中心发生什么情况,我们都必须确保状态得以保留。
保存应用状态的方式取决于其架构。有些应用将数据存储在内存中,并依赖定期备份;有些则能够在多个副本之间同步数据,从而即使某个实例失效也不会导致数据丢失;而大多数应用则依赖磁盘来存储其状态。我们将重点关注这类有状态的应用。
如果我们希望构建容错系统,就必须确保系统任何部分的故障都是可恢复的。由于速度至关重要,我们不能依赖手动操作来应对故障。即使可以做到,也没有人愿意坐在屏幕前等待某个组件失败,然后再将其恢复到之前的状态。
Kubernetes 的故障处理机制
我们已经看到,Kubernetes 在大多数情况下能够从应用故障、服务器故障甚至整个数据中心故障中恢复。它会将 Pod 重新调度到健康的节点上。我们也体验过 AWS 和 kOps 如何在基础设施层面实现类似的效果:自动扩展组(Auto Scaling Groups)会重建失败的节点,而由于这些节点通过 kOps 启动流程进行配置,新实例将具备所需的一切,并自动加入集群。
唯一阻碍我们宣称系统“基本”具备高可用性和容错能力的因素,就是尚未解决跨故障场景下的状态持久化问题。这正是我们接下来要探讨的主题。
我们将尝试确保无论有状态应用或其运行服务器发生何种情况,数据都能得到保护。
创建 Kubernetes 集群
我们将重新创建一个与前一章类似的集群。
1cd cluster
进入本地 k8s-specs 仓库的副本,拉取最新代码,并切换到 cluster 目录。
设置环境变量
在前一章中,我们将使用的环境变量存储在 kops 文件中。让我们快速查看一下:
1cat kops
输出内容(不含密钥)如下:
1export AWS_ACCESS_KEY_ID=... 2export AWS_SECRET_ACCESS_KEY=... 3export AWS_DEFAULT_REGION=us-east-2 4export ZONES=us-east-2a,us-east-2b,us-east-2c 5export NAME=devops23.k8s.local 6export KOPS_STATE_STORE=s3://devops23-1520933480
通过将环境变量保存在文件中,我们可以使用 source 命令快速加载它们,从而加快流程。
注意: 请确保你的文件中所有以
export开头的行都存在。如果缺失,请相应补充。
1source kops
创建 S3 存储桶
环境变量设置完成后,我们可以继续创建 S3 存储桶。
1export BUCKET_NAME=devops23-$(date +%s) 2 3aws s3api create-bucket \ 4 --bucket $BUCKET_NAME \ 5 --create-bucket-configuration \ 6 LocationConstraint=$AWS_DEFAULT_REGION 7 8export KOPS_STATE_STORE=s3://$BUCKET_NAME
仅限 Windows 用户
如果你是 Windows 用户,请执行以下命令来创建 kops 别名:
1alias kops="docker run -it --rm \ 2 -v $PWD/devops23.pub:/devops23.pub \ 3 -v $PWD/config:/config \ 4 -e KUBECONFIG=/config/kubecfg.yaml \ 5 -e NAME=$NAME -e ZONES=$ZONES \ 6 -e AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID \ 7 -e AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY \ 8 -e KOPS_STATE_STORE=$KOPS_STATE_STORE \ 9 vfarcic/kops"
集群创建
现在我们可以开始在 AWS 上创建新的 Kubernetes 集群。
1kops create cluster \ 2 --name $NAME \ 3 --master-count 3 \ 4 --master-size t2.small \ 5 --node-count 2 \ 6 --node-size t2.medium \ 7 --zones $ZONES \ 8 --master-zones $ZONES \ 9 --ssh-public-key devops23.pub \ 10 --networking kubenet \ 11 --yes
将此命令与前一章执行的命令对比,你会发现只有少数几处微小差异:我们将 node-count 提升至 2,node-size 改为 t2.medium。这足以满足本章练习所需的资源容量。
验证集群
让我们验证集群是否已成功创建:
1kops validate cluster
假设自执行 kops create cluster 以来已过去足够时间,输出应显示 cluster devops23.k8s.local is ready。
注意: 请等待验证检查全部通过。
给 Windows 用户的一点提示
注意: 此提示仅适用于 Windows 用户。kOps 在容器中运行,其内部上下文已被更改,而本地的
kubectl上下文保持不变。我们需要通过执行kops export kubecfg --name ${NAME}和export KUBECONFIG=$PWD/config/kubecfg.yaml来修复这个问题。第一条命令将配置导出到/config/kubecfg.yaml,该路径由环境变量KUBECONFIG指定,并挂载为本地硬盘上的config/kubecfg.yaml。第二条命令将KUBECONFIG导出到本地环境。通过这个变量,kubectl现在将使用config/kubecfg.yaml中的配置,而非默认配置。在运行这些命令前,请给 AWS 几分钟时间,以便完成所有 EC2 实例的创建并加入集群。等待完成后执行上述命令,即可完成配置。
创建 Ingress 和 ELB DNS
为了访问我们后续部署的应用,我们需要配置 Ingress。
1kubectl create \ 2 -f https://raw.githubusercontent.com/kubernetes/kops/master/addons/ingress-nginx/v1.6.0.yaml
Ingress 本身无法发挥作用,除非配合 ELB DNS。因此我们同时获取 ELB DNS。
1CLUSTER_DNS=$(aws elb \ 2 describe-load-balancers | jq -r \ 3 ".LoadBalancerDescriptions[] \ 4 | select(.DNSName \ 5 | contains (\"api-devops23\") \ 6 | not).DNSName") 7 8echo $CLUSTER_DNS
后一条命令的输出应以 us-east-2.elb.amazonaws.com 结尾。
至此,集群设置已完成,我们可以返回到仓库根目录。
1cd ..
在下一课中,我们将部署有状态应用,但暂时不考虑其状态的持久化。