如何在AWS中国区使用kops

入门

​ Kops过去只支持Google Cloud DNS和Amazon Route53配置kubernetes集群。 但是从1.6.2添加了gossip,因此可以在没有这些DNS提供商的情况下配置群集。 感谢gossip,从1.7开始正式支持在AWS中国地区没有Route53的情况下提供功能齐全的kubernetes群集。 目前只有cn-north-1(北京区)可用,但新的地区即将推出

以下大多数配置集群的过程与在AWS中使用kops的指南相同。 所以下面主要描述在中国区使用的不同点,相似的部分将被省略。

Install kops

Install kubectl

Setup your environment

AWS

当执行 aws configure 时,请记住将默认区域名称设置为正确的名称,例如,cn-north-1。

AWS Access Key ID [None]:
AWS Secret Access Key [None]:
Default region name [None]:
Default output format [None]:

并正确导出它。

export AWS_REGION=$(aws configure get region)

配置 DNS

正如一开始提到的那样,通过让群集名以.k8s.loca l结尾,可以很容易地创建一个基于gossip的群集。 我们将在下面采用这个技巧。 其余部分可以安全地跳过。

Testing your DNS setup

由于gossip,这部分也可以安全地跳过。

群集状态存储

由于我们正在AWS中国地区部署集群,因此我们需要在AWS中国地区创建一个专用S3存储桶。

aws s3api create-bucket --bucket prefix-example-com-state-store --create-bucket-configuration LocationConstraint=$AWS_REGION

创建你的第一个集群

确保你有一个可以正常访问互联网的VPC

首先,我们必须解决与中国以外的互联网的缓慢和不稳定的连接,否则以下流程将无法工作。 一种方法是建立一个NAT实例,通过一些可靠的连接路由流量。 细节将不在这里讨论。

准备 kops ami

我们必须建立自己的AMI,因为AWS中国地区没有官方的kops ami。 有两种方法可以实现。

ImageBuilder

首先,在一个私有子网中启动一个快速稳定访问互联网的实例。

因为实例在私有子网中启动,所以我们需要确保它可以通过VPN或bastion使用私有IP进行连接。

SUBNET_ID=<subnet id> # 私有子网ID
SECURITY_GROUP_ID=<security group id>
KEY_NAME=<key pair name on aws>

AMI_ID=$(aws ec2 describe-images --filters Name=name,Values=debian-jessie-amd64-hvm-2016-02-20-ebs --query 'Images[*].ImageId' --output text)
INSTANCE_ID=$(aws ec2 run-instances --image-id $AMI_ID --instance-type m3.medium --key-name $KEY_NAME --security-group-ids $SECURITY_GROUP_ID --subnet-id $SUBNET_ID --no-associate-public-ip-address --query 'Instances[*].InstanceId' --output text)
aws ec2 create-tags --resources ${INSTANCE_ID} --tags Key=k8s.io/role/imagebuilder,Value=1

现在按照kube-deploy中的ImageBuilder文档构建镜像。

go get k8s.io/kube-deploy/imagebuilder
cd ${GOPATH}/src/k8s.io/kube-deploy/imagebuilder

sed -i '' "s|publicIP := aws.StringValue(instance.PublicIpAddress)|publicIP := aws.StringValue(instance.PrivateIpAddress)|" pkg/imagebuilder/aws.go
make

# If the keypair specified is not `$HOME/.ssh/id_rsa`, `aws.yaml` need to be modified to add the full path to the private key.
echo 'SSHPrivateKey: "/absolute/path/to/the/private/key"' >> aws.yaml

${GOPATH}/bin/imagebuilder --config aws.yaml --v=8 --publish=false --replicate=false --up=false --down=false

注意

imagebuilder可能会抱怨镜像在构建和执行失败后找不到。 但是从异常日志中,我们可以发现AMI已经被实际注册了。 尽管bootstrap-vz声称有这个问题,但这似乎新创建的AMI暂时处理不可用状态导致的。 kubernetes/kube-deploy#293

等一分钟左右,AMI应该可以使用了。

从另一个地区复制AMI

这个评论在从其他区域复制kops镜像,例如:ap-southeast-1

获取AMI ID

无论使用何种方式,我们最终得到AMI,例如,k8s-1.7-debian-jessie-amd64-hvm-ebs-2017-09-09。

准备本地环境

设置几个环境变量。

export NAME=example.k8s.local
export KOPS_STATE_STORE=s3://prefix-example-com-state-store

创建集群配置

我们需要注意哪些可用区域可供我们使用。 AWS中国(北京)地区只有两个可用区域。 它会有同样的问题,像其他地区少于三个AZ,在两个AZ上没有真正的HA支持。 但可以添加更多主节点来提高一个AZ的可靠性。

aws ec2 describe-availability-zones

下面是 create cluster 命令,它将在现有的VPC中创建一个完整的内部群集。 以下命令将生成群集配置,但不会开始构建它(不会启动服务器)。 确保在创建群集之前生成了SSH密钥对。

VPC_ID=<vpc id>
VPC_NETWORK_CIDR=<vpc network cidr> # e.g. 172.30.0.0/16
AMI=<owner id/ami name> # e.g. 123456890/k8s-1.7-debian-jessie-amd64-hvm-ebs-2017-09-09

kops create cluster \
    --zones ${AWS_REGION}a \
    --vpc ${VPC_ID} \
    --network-cidr ${VPC_NETWORK_CIDR} \
    --image ${AMI} \
    --associate-public-ip=false \
    --api-loadbalancer-type internal \
    --topology private \
    --networking weave \
    ${NAME}

自定义群集配置

现在我们有一个集群配置文件,我们通过编辑描述来调整子网配置以重用共享子网

kops edit cluster $NAME

然后更改相应的子网以指定该子网id并除去cidr,例如

spec:
  subnets:
  - id: subnet-12345678
    name: cn-north-1a
    type: Private
    zone: cn-north-1a
  - id: subnet-87654321
    name: utility-cn-north-1a
    type: Utility
    zone: cn-north-1a

我们在这里可以采用的另一个调整是添加一个docker配置,将镜像更改为中国的官方注册表镜像。 这将增加从docker hub中拉取镜像的稳定性和下载速度。

spec:
  docker:
    logDriver: ""
    registryMirrors:
    - https://registry.docker-cn.com

请注意,这面镜子请注意,这面可能**不适合某些情况。 只要它与docker API兼容,它就可以被任何其他注册表镜像替换。不适合某些情况。 只要它与docker API兼容,它就可以被任何其他注册表镜像替换。

Build the Cluster

Use the Cluster

Delete the Cluster

What's next?

添加更多主结点

一个 AZ

为了达到这个目的,我们可以添加更多参数给kops create cluster

  --master-zones ${AWS_REGION}a --master-count 3 \
  --zones ${AWS_REGION}a --node-count 2 \

两个 AZ

  --master-zones ${AWS_REGION}a,${AWS_REGION}b --master-count 3 \
  --zones ${AWS_REGION}a,${AWS_REGION}b --node-count 2 \

请注意,当其中一个AZ宕机时,这仍有50%的可能性导致集群不可用。

离线模式

这是一个天真的,未完成的尝试,以最小化互联网需求的方式配置群集,因为即使使用某种代理或VPN,它仍然不是那么快,而且总是比从S3下载要贵得多。

## Setup vars

KUBERNETES_VERSION=$(curl -fsSL --retry 5 "https://dl.k8s.io/release/stable.txt")
KOPS_VERSION=$(curl -fsSL --retry 5 "https://api.github.com/repos/kubernetes/kops/releases/latest" | grep 'tag_name' | cut -d\" -f4)
ASSET_BUCKET="some-asset-bucket"
ASSET_PREFIX=""

# Please note that this filename of cni asset may change with kubernetes version
CNI_FILENAME=cni-0799f5732f2a11b329d9e3d51b9c8f2e3759f2ff.tar.gz


export KOPS_BASE_URL=https://s3.cn-north-1.amazonaws.com.cn/$ASSET_BUCKET/kops/$KOPS_VERSION/
export CNI_VERSION_URL=https://s3.cn-north-1.amazonaws.com.cn/$ASSET_BUCKET/kubernetes/network-plugins/$CNI_FILENAME

## Download assets

KUBERNETES_ASSETS=(
  network-plugins/$CNI_FILENAME
  release/$KUBERNETES_VERSION/bin/linux/amd64/kube-apiserver.tar
  release/$KUBERNETES_VERSION/bin/linux/amd64/kube-controller-manager.tar
  release/$KUBERNETES_VERSION/bin/linux/amd64/kube-proxy.tar
  release/$KUBERNETES_VERSION/bin/linux/amd64/kube-scheduler.tar
  release/$KUBERNETES_VERSION/bin/linux/amd64/kubectl
  release/$KUBERNETES_VERSION/bin/linux/amd64/kubelet
)
for asset in "${KUBERNETES_ASSETS[@]}"; do
  dir="kubernetes/$(dirname "$asset")"
  mkdir -p "$dir"
  url="https://storage.googleapis.com/kubernetes-release/$asset"
  wget -P "$dir" "$url"
  [ "${asset##*.}" != "gz" ] && wget -P "$dir" "$url.sha1"
  [ "${asset##*.}" == "tar" ] && wget -P "$dir" "${url%.tar}.docker_tag"
done

KOPS_ASSETS=(
  "images/protokube.tar.gz"
  "linux/amd64/nodeup"
  "linux/amd64/utils.tar.gz"
)
for asset in "${KOPS_ASSETS[@]}"; do
  kops_path="kops/$KOPS_VERSION/$asset"
  dir="$(dirname "$kops_path")"
  mkdir -p "$dir"
  url="https://kubeupv2.s3.amazonaws.com/kops/$KOPS_VERSION/$asset"
  wget -P "$dir" "$url"
  wget -P "$dir" "$url.sha1"
done

## Upload assets

## Get default S3 multipart_threshold

AWS_S3_DEFAULT_MULTIPART_THRESHOLD=$(aws configure get default.s3.multipart_threshold)

if [ ! -n "$AWS_S3_DEFAULT_MULTIPART_THRESHOLD" ]; then
  AWS_S3_DEFAULT_MULTIPART_THRESHOLD=8MB
fi

## Set multipart_threshold to 1024MB to prevent Etag not returns MD5 when upload multipart

aws configure set default.s3.multipart_threshold 1024MB

aws s3api create-bucket --bucket $ASSET_BUCKET --create-bucket-configuration LocationConstraint=$AWS_REGION
for dir in "kubernetes" "kops"; do
  aws s3 sync --acl public-read "$dir" "s3://$ASSET_BUCKET/$ASSET_PREFIX$dir"
done

aws configure set default.s3.multipart_threshold $AWS_S3_DEFAULT_MULTIPART_THRESHOLD

创建群集时,将这些参数添加到命令行。

  --kubernetes-version https://s3.cn-north-1.amazonaws.com.cn/$ASSET_BUCKET/kubernetes/release/$KUBERNETES_VERSION

现在,通过kops和kubernetes设置集群所需的大部分资源将从指定的S3存储桶下载,但pause-amd64,dns相关等images除外。由于托管在gcr.io上,因此Docker Hub镜像里没有这些images。如果不能科学上网,会有一些问题。

Assets API

它没有经过测试,因为当作者在AWS中国区域尝试提供集群时,这种方法只是PR。这是实现离线模式的官方方式,应该优于以前的天真尝试。