在 Amazon Web Services (AWS) 上部署 Kubernetes#
AWS 没有为 Kubernetes 提供原生支持,但有许多组织已经整理出了自己的解决方案和指南,用于在 AWS 上设置 Kubernetes。
本指南使用 kops 在 AWS 上设置集群。这应该被看作是一个粗略的模板,您将用它来设置和塑造您的集群。
步骤#
创建一个 IAM(身份和访问管理)角色。
此角色将用于授予您的 CI 主机在 AWS 上创建和销毁资源的权限。创建角色的说明可以在这里找到。需要以下策略:
AmazonEC2FullAccess
IAMFullAccess
AmazonS3FullAccess
AmazonVPCFullAccess
Route53FullAccess(可选)
创建一个新实例作为您的 CI 主机。此节点将处理集群的配置和拆除。
此实例可以很小(例如 t2.micro)。
创建时,分配在步骤 1 中创建的 IAM 角色。
创建后,下载 ssh 密钥(.pem 文件)。确保该文件的权限是受限的。
chmod 400 name.pem
通过 SSH 连接到您的 CI 主机。如何操作的说明在这里给出。
在您的 CI 主机上安装 kops 和 kubectl。
请遵循此处的说明:kubernetes/kops
选择一个集群名称。
由于我们不使用预配置的 DNS,我们将使用后缀“.k8s.local”。根据文档,如果 DNS 名称以 .k8s.local 结尾,集群将使用内部托管的 DNS。
export NAME=<somename>.k8s.local
设置一个用于集群的 ssh 密钥对。
ssh-keygen
创建一个 S3 存储桶来存储您的集群配置。
由于我们在 AWS 上,我们可以使用 S3 作为后端存储。建议在 S3 存储桶上启用版本控制。我们不需要将此信息传递给 KOPS 命令。kops 工具会将其作为一个环境变量自动检测到。
export KOPS_STATE_STORE=s3://<your_s3_bucket_name_here>
设置部署区域。
export REGION=`curl -s http://169.254.169.254/latest/dynamic/instance-identity/document|grep region|awk -F\" '{print $4}'`
安装 AWS CLI。
sudo apt-get update sudo apt-get install awscli
设置节点的可用区。
在本指南中,我们将允许节点部署在所有可用区(AZ)。
export ZONES=$(aws ec2 describe-availability-zones --region $REGION | grep ZoneName | awk '{print $2}' | tr -d '"')
创建集群。
对于基本设置,运行以下命令(所有大小均以 GB 为单位):
kops create cluster $NAME \ --zones "$ZONES" \ --authorization RBAC \ --master-size t3a.small \ --master-volume-size 10 \ --node-size t3.medium \ --node-volume-size 10 \ --yes
对于更安全的设置,请向 kops 命令添加以下参数:
--topology private \ --networking weave \
这将创建一个所有主节点和工作节点都位于私有子网中且没有外部 IP 地址的集群。配置错误的安全组或不安全的 ssh 配置不太可能危及集群。为了通过 SSH 连接到您的集群,您需要设置一个堡垒机节点。请确保您在下面完成该步骤。如果您拥有默认数量的弹性 IP(10个),您可能需要向 AWS 支持提出请求以提高该限制。另一种方法是减少指定的可用区数量。
关于此主题的更多阅读:https://github.com/kubernetes/kops/blob/HEAD/docs/networking.md
需要考虑的设置(本指南未涵盖):
--vpc Allows you to use a custom VPC or share a VPC https://github.com/kubernetes/kops/blob/HEAD/docs/run_in_existing_vpc.md --master-count Spawns more masters in one or more VPCs This improves redudancy and reduces downtime during cluster upgrades --master-zones specify zones to run the master in --node-count Increases the total nodes created (default 2) --master/node-security-groups Allows you to specify additional security groups to put the masters and nodes in by default --ssh-access By default SSH access is open to the world (0.0.0.0). If you are using a private topology, this is not a problem. If you are using a public topology make sure your ssh keys are strong and you keep sshd up to date on your cluster's nodes.
考虑为您的 AWS 账户设置云预算,以确保您不会意外超出预期支出。
等待集群启动。
运行
kops validate cluster
命令会告诉我们当前的设置状态。如果您最初看到“can not get nodes”(无法获取节点),请耐心等待,因为集群只有在一些基本服务启动并运行后才能报告状态。继续运行
kops validate cluster
直到您在输出的末尾看到“Your cluster $NAME is ready”(您的集群 $NAME 已就绪)。time until kops validate cluster; do sleep 15; done
可用于自动化等待过程。
如果在此步骤后您希望随时销毁集群,请运行
kops delete cluster $NAME --yes
。确认
kubectl
已连接到您的 Kubernetes 集群。运行
kubectl get nodes
您应该看到一个包含两个节点的列表,每个节点都以
ip
开头。如果您想在本地使用 kubectl 和 helm
在 CI 主机上运行以下命令:
kops export kubecfg
将
~/.kube/config
的内容复制到您本地系统上的相同位置。
如果您希望将 kube 配置文件放在不同的位置,您需要运行
export KUBECONFIG=<other kube config location>
配置 ssh 堡垒机(如果您没有选择上面的 –topology private 选项,请跳过此步骤!)
理想情况下,我们只需在上面的 kops 命令中传递
--bastion
标志。然而,该标志目前并未按预期工作。kubernetes/kops#2881因此,我们需要遵循本指南:kubernetes/kops
此时,还有一些开放的公共端点需要处理。
堡垒机 ELB 安全组默认为允许来自 0.0.0.0 的访问。
API ELB 安全组默认为允许来自 0.0.0.0 的访问。
在您的 Kubernetes 集群上启用动态存储。
在您的本地计算机上创建一个名为
storageclass.yml
的文件,并输入以下文本:kind: StorageClass apiVersion: storage.k8s.io/v1 metadata: annotations: storageclass.beta.kubernetes.io/is-default-class: "true" name: gp2 provisioner: kubernetes.io/aws-ebs parameters: type: gp2
接下来,运行此命令:
kubectl apply -f storageclass.yml
这启用了磁盘的动态置备,允许我们在用户登录 JupyterHub 时自动为每个用户分配一个磁盘。
注意
EC2 实例元数据是详细说明正在运行实例的配置和运行情况的数据。这些数据可能很敏感,任何有权直接访问该实例的人都可以看到。默认情况下,这些元数据会被一个 init-container 阻止,因为它们会覆盖用于设置实例的
iptables
。可以通过在 init-container 中添加一个iptables
规则来设置和保护对此元数据的访问,如云元数据安全部分的此处 <https://zero-to-jupyterhub.readthedocs.io/en/v0.5-doc/security.html>
_所示。
加密#
有简单的方法可以加密您的 Kubernetes 集群。这里展示了静态加密和传输中加密的简单方法。
静态加密
不要执行上面的步骤 13,而是在您的本地计算机上创建以下 storageclass.yml
文件:
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
annotations:
storageclass.beta.kubernetes.io/is-default-class: "true"
name: gp2
provisioner: kubernetes.io/aws-ebs
parameters:
type: gp2
encrypted: "true"
主要区别是增加了 encrypted: "true"
这一行,并请注意 true
是在双引号内的。
接下来运行这些命令:
kubectl delete storageclass gp2
kubectl apply -f storageclass.yml
Kubernetes 不允许您修改 storageclass gp2 来添加 encrypted
标志,因此您必须先删除它。这将加密由 Kubernetes 创建的任何动态卷(例如您的笔记本),但不会加密 Kubernetes 节点本身的存储。
传输中加密
在上面的步骤 9 中,通过在 kops create
命令中包含 --networking weave
标志来设置使用 weave 的集群。然后执行以下步骤:
验证 weave 正在运行。
kubectl --namespace kube-system get pods
您应该看到几个形如
weave-net-abcde
的 pod。使用足够强度的私有密码创建 Kubernetes secret。本例中使用了一个随机的 128 字节密码。
openssl rand -hex 128 >weave-passwd kubectl create secret -n kube-system generic weave-passwd --from-file=./weave-passwd
重要的是,secret 名称及其值(取自文件名)必须相同。如果它们不匹配,您可能会得到一个
ConfigError
。用密码修补 Weave。
kubectl patch --namespace=kube-system daemonset/weave-net --type json -p '[ { "op": "add", "path": "/spec/template/spec/containers/0/env/0", "value": { "name": "WEAVE_PASSWORD", "valueFrom": { "secretKeyRef": { "key": "weave-passwd", "name": "weave-passwd" } } } } ]'
如果您想移除加密,可以使用以下补丁:
kubectl patch --namespace=kube-system daemonset/weave-net --type json -p '[ { "op": "remove", "path": "/spec/template/spec/containers/0/env/0"} ]'
检查 pod 是否已重启。为了加快进程,您可以删除旧的 pod。
您可以使用以下命令验证加密是否已开启:
kubectl exec -n kube-system weave-net-<pod> -c weave -- /home/weave/weave --local status
您应该看到
encryption: enabled
。如果您真的想确保加密正在工作,您可以在任何节点的
6783
端口上监听。如果流量看起来像乱码,您就知道加密已开启。