Описание
Продолжение проекта, описанного в посте AWS: билд Java + Maven + Docker + Packer + Terraform – будем разворачивать нечто аналогичное в Китае.
Хотя у Китая есть “свой AWS” – Aliyun.com, принадлежащий Alibaba Group, тем не менее – мы будем пользоваться именно Amazon Web Services.
В этом посте не будет HowTo do something – больше просто описание опыта работы с Китаем.
Пара полезных ссылок:
- Introducing AWS in China – оф. описание от Amazon
- AWS China(Beijing) Region Tips – про особенности работы с AWS China
Сервисы
Первое, что бросается в глаза – это количество сервисов – тут их намного меньше.
Например, консоль в Европе выглядит так:
А в Китае – так:
Список всех сервисов и их наличие по регионам можно посмотреть тут>>>.
Скорость
Вторая проблема – скорость.
Например, открыть страницу китайского AWS, даже просто curl
-ом, из Киева:
[simterm]
$ time curl https://www.amazonaws.cn/en/ ... real 0m30.267s user 0m0.027s
[/simterm]
Тест скорости с iperf
из датацентра “Воля” в Киеве:
[simterm]
ubuntu@ip-172-31-14-50:~$ iperf -s ------------------------------------------------------------ Server listening on TCP port 5001 TCP window size: 85.3 KByte (default) ------------------------------------------------------------ [ 4] local 172.31.14.50 port 5001 connected with 77.120.103.20 port 36174 [ ID] Interval Transfer Bandwidth [ 4] 0.0-53.3 sec 384 KBytes 59.1 Kbits/sec
[/simterm]
59.1 Kbits/sec? Где-то такое уже видели, только 56к:
На самом деле скорость варьируется – иногда всё работает более-менее живо, иногда – отмирает напрочь.
ICP license
Ещё один немаловажный (критический, я бы сказал момент) – это ICP license.
Вопросами лицензии занимались менеджеры, потому деталей не знаю, но хороший обзор на эту тему есть тут>>>.
Кратко говоря – вы не можете запустить вебсайт (вообще любой сервис, который работает по портам 80, 443, пока не знаю по поводу 8080 и использует доменное имя), не получив разрешения от властей Китая, а именно – от Ministry of Industry and Information Technology. Не в курсе – как на счёт других сервисов (почта, базы и т.д.), но что касается веб – без лицензии не обойтись.
Пример лицензии можно увидеть тут – http://bj.58.com, слева внизу:
Или даже на странице самого китайского AWS Console:
Процесс получения лицезии выглядит примерно так:
Начало работы
Начнём работу с настройки профиля:
[simterm]
$ aws configure --profile tag-cn AWS Access Key ID [None]: AKI***L5A AWS Secret Access Key [None]: OtN***7Cb Default region name [None]: cn-north-1 Default output format [None]: json
[/simterm]
Образы Ubuntu, как обычно – можно найти на Ubuntu Amazon EC2 AMI Finder.
И первый “упс” – в Китае нет t2.nano
:
[simterm]
$ aws ec2 run-instances --image-id ami-a163b4cc --key-name tag-cn --instance-type t2.nano --profile tag-cn An error occurred (Unsupported) when calling the RunInstances operation: The requested configuration is currently not supported. Please check the documentation for supported configurations.
[/simterm]
Docker test
Запускаем интанс:
[simterm]
$ aws ec2 run-instances --image-id ami-a163b4cc --key-name tag-cn --instance-type t2.micro --profile tag-cn
[/simterm]
Первое, что требуется проверить – скорость загрузки образов с серверов JFrog Artifactory, которые расположены в Европе.
Планируется использование уже имеющегося Jenkins в Европе, который будет собирать образы и пушить их в Artifactory, после чего скрипт на китайских инстансах будет делать docker pull
и переключать Blue и Green окружения.
Устанавливаем Docker:
[simterm]
# time wget -qO- https://get.docker.com/ | sh
[/simterm]
Скорость… При apt-get update
, даже несмотря на то, что большая часть данных тянется из китайского репозитория Ubuntu (http://cn-north-1b.clouds.archive.ubuntu.com/ubuntu) – update
выполнялся минут 10, а весь процесс установки Docker из этого скрипта – минут 30.
Ждём, несколько раз отлавливая ошибки вида:
…
E: Failed to fetch https://apt.dockerproject.org/repo/pool/main/d/docker-engine/docker-engine_17.04.0~ce-0~ubuntu-xenial_amd64.deb Operation too slow. Less than 10 bytes/sec transferred the last 120 seconds
…
Собственно – попытка pull
:
[simterm]
root@ip-172-31-14-50:~# time docker pull engineering-tag-docker.jfrog.io/tag-configuration:production-rc_2017april-24 production-rc_2017april-24: Pulling from tag-configuration ec37562cf8fa: Pull complete 2f029489f597: Pull complete c274fc74f91c: Pull complete 9ed2daf3bbcb: Pull complete 1e68211e62fb: Pull complete Digest: sha256:6c9d700f8d0c4c59ba693ffed1bb23c06ef5f573b71e86d911471e8f054d208a Status: Downloaded newer image for engineering-tag-docker.jfrog.io/tag-configuration:production-rc_2017april-24 real 7m48.104s user 0m0.072s sys 0m0.024s
[/simterm]
Почти 8 минут для образа в 237 мб – для нас приемлемо, тем более последующие загрузки будут быстрее.
Terraform
Для создания окружений (и для деплоя, но не в этом случае) – у нас имеются шаблоны Terrafrom:
[simterm]
$ ls -l ../../tag-server-api-infrastructure/terraform total 104 -rw-r--r-- 1 setevoy setevoy 5582 Dec 27 16:24 api.tf drwxr-xr-x 2 setevoy setevoy 4096 Feb 16 12:21 autoscaling_group_blue drwxr-xr-x 2 setevoy setevoy 4096 Dec 27 16:24 autoscaling_group_green drwxr-xr-x 2 setevoy setevoy 4096 Dec 27 16:24 autoscaling_policy drwxr-xr-x 2 setevoy setevoy 4096 Dec 27 16:24 elb -rw-r--r-- 1 setevoy setevoy 3271 Dec 27 16:24 eureka.tf drwxr-xr-x 3 setevoy setevoy 4096 Dec 27 16:24 files drwxr-xr-x 2 setevoy setevoy 4096 May 3 15:52 launch_configuration drwxr-xr-x 2 setevoy setevoy 4096 Dec 27 16:24 nat -rw-r--r-- 1 setevoy setevoy 648 Dec 27 16:24 nat.tf -rw-r--r-- 1 setevoy setevoy 128 Dec 27 16:24 provider.tf -rw-r--r-- 1 setevoy setevoy 3072 Feb 20 14:15 security_group_api_ec2.tf -rw-r--r-- 1 setevoy setevoy 2238 Dec 27 16:24 security_group_api_elb.tf -rw-r--r-- 1 setevoy setevoy 395 Dec 27 16:24 security_group_default.tf -rw-r--r-- 1 setevoy setevoy 710 Dec 27 16:24 security_group_eureka.tf -rw-r--r-- 1 setevoy setevoy 1546 Dec 27 16:24 security_group_http_out.tf -rw-r--r-- 1 setevoy setevoy 2347 Feb 20 14:15 security_group_nat.tf -rw-r--r-- 1 setevoy setevoy 786 Dec 27 16:24 security_group_ssh_private.tf -rw-r--r-- 1 setevoy setevoy 409 Dec 27 16:24 security_group_ssh_trusted.tf -rwxr-xr-x 1 setevoy setevoy 3203 May 3 14:46 terraform-cn.sh -rw-r--r-- 1 setevoy setevoy 3654 May 3 14:49 variables.tf -rw-r--r-- 1 setevoy setevoy 131 Dec 27 16:24 vpc_internet_gateway.tf -rw-r--r-- 1 setevoy setevoy 1224 Dec 27 16:24 vpc_route_table.tf -rw-r--r-- 1 setevoy setevoy 975 Dec 27 16:24 vpc_subnets.tf -rw-r--r-- 1 setevoy setevoy 126 Dec 27 16:24 vpc.tf
[/simterm]
А для быстрого запуска – я когда-то писал bash
-скрипт:
#!/usr/bin/env bash # Do NOT use thi script ever! # For testing environmtnt only AWS_ACCESS_KEY_ID="AKI***L5A" AWS_SECRET_ACCESS_KEY="OtN***7Cb" AWS_REGION="cn-north-1" USERNAME="docker" PASSWORD="M8f***XSC" DOCKER_TAG=$1 [[ -z $DOCKER_TAG ]] && { echo "Specify Docker tag as first argument."; exit 1; } TF_BACK_PATH="dev-cn" EC2KEY="tag-cn" VPC_CIDR="10.0.0.0/16" SPRING_PROFILE=dev-cn terraform get terraform_config () { terraform remote config \ -backend=artifactory \ -backend-config="username=${USERNAME}" \ -backend-config="password=${PASSWORD}" \ -backend-config="url=https://engineering.artifactoryonline.com/engineering/tag-terraform/" \ -backend-config="repo=api" \ -backend-config="subpath=${TF_BACK_PATH}" } terraform_plan () { terraform plan \ -var region=${AWS_REGION} \ -var aws_access_key=${AWS_ACCESS_KEY_ID} \ -var aws_secret_key=${AWS_SECRET_ACCESS_KEY} \ -var ssh_key_name=${EC2KEY} \ -var vpc_cidr_block=${VPC_CIDR} \ -var 'public_subnet_cidr_blocks={ "0" = "10.0.0.0/24", "1" = "10.0.1.0/24" }' \ -var 'private_subnet_cidr_blocks={ "0" = "10.0.2.0/24", "1" = "10.0.3.0/24" }' \ -var spring_profile=${SPRING_PROFILE} \ -var docker_image_tag=${DOCKER_TAG} \ -var min_size_green=1 \ -var min_size_blue=0 \ -var max_size=8 } terraform_apply () { terraform apply \ -var region=${AWS_REGION} \ -var aws_access_key=${AWS_ACCESS_KEY_ID} \ -var aws_secret_key=${AWS_SECRET_ACCESS_KEY} \ -var ssh_key_name=${EC2KEY} \ -var vpc_cidr_block=${VPC_CIDR} \ -var 'public_subnet_cidr_blocks={ "0" = "10.0.0.0/24", "1" = "10.0.1.0/24" }' \ -var 'private_subnet_cidr_blocks={ "0" = "10.0.2.0/24", "1" = "10.0.3.0/24" }' \ -var spring_profile=${SPRING_PROFILE} \ -var docker_image_tag=${DOCKER_TAG} } terraform_plan_destroy () { terraform plan -destroy \ -var region=${AWS_REGION} \ -var aws_access_key=${AWS_ACCESS_KEY_ID} \ -var aws_secret_key=${AWS_SECRET_ACCESS_KEY} \ -var ssh_key_name=${EC2KEY} \ -var vpc_cidr_block=${VPC_CIDR} \ -var 'public_subnet_cidr_blocks={ "0" = "10.0.0.0/24", "1" = "10.0.1.0/24" }' \ -var 'private_subnet_cidr_blocks={ "0" = "10.0.2.0/24", "1" = "10.0.3.0/24" }' \ -var spring_profile=${SPRING_PROFILE} } terraform_destroy () { terraform destroy \ -var region=${AWS_REGION} \ -var aws_access_key=${AWS_ACCESS_KEY_ID} \ -var aws_secret_key=${AWS_SECRET_ACCESS_KEY} \ -var ssh_key_name=${EC2KEY} \ -var vpc_cidr_block=${VPC_CIDR} \ -var 'public_subnet_cidr_blocks={ "0" = "10.0.0.0/24", "1" = "10.0.1.0/24" }' \ -var 'private_subnet_cidr_blocks={ "0" = "10.0.2.0/24", "1" = "10.0.3.0/24" }' \ -var spring_profile=${SPRING_PROFILE} } #terraform_config || exit 1 #terraform_plan || exit 1 terraform_apply || exit 1 #terraform_plan_destroy || exit 1 #terraform_destroy || exit 1
Запускаем, пробуем:
[simterm]
$ ./terraform-cn.sh production-rc_2017april-24 Get: file:///home/setevoy/Work/LON.TAG/tag-server-api-infrastructure/terraform/launch_configuration ... Get: file:///home/setevoy/Work/LON.TAG/tag-server-api-infrastructure/terraform/nat ... data.template_file.eureka_userdata: Refreshing state... data.template_file.api_userdata: Refreshing state... data.aws_ami.nat: Refreshing state... data.aws_ami.eureka_blue: Refreshing state... data.aws_ami.api_blue: Refreshing state... data.aws_ami.api_green: Refreshing state... data.aws_ami.eureka_green: Refreshing state... Error refreshing state: 1 error(s) occurred: * data.aws_ami.eureka_green: 1 error(s) occurred: * data.aws_ami.eureka_green: data.aws_ami.eureka_green: AuthFailure: AWS was not able to validate the provided access credentials status code: 401, request id: 76509ce4-e07c-42b2-bdbf-a4e80e877d1c
[/simterm]
Странно, но ок – добавляем AIM роль AdministratorAccess
, пробуем снова (прим. – роль администратора не помогла, см. ниже).
Вторая ошибка – из-за соединения. Работа из Киева в Китай будет аукаться ещё много раз:
…
* aws_security_group.http_out: Error waiting for Security Group (sg-e7fa5f83) to become available: timeout while waiting for state to become ‘exists’ (timeout: 1m0s)
…
Перезапускаем.
Проблемы
Ещё одна ошибка:
Просто консоль не сумела подгрузить данные. Ну, ок…
Вот ещё – Connection reset:
Ещё ошибка:
А ещё можем так:
Так мы и закончили первый день… 🙂
Ещё несколько раз выскакивала ошибка вида:
…
* data.aws_ami.eureka_green: data.aws_ami.eureka_green: AuthFailure: AWS was not able to validate the provided access credentials
status code: 401, request id: c534dca9-d35f-408c-a310-86bf1bfc53dc
…
Но перезапуск помогал. Причём появляется она рандомно, независимо от типа ресурса – иногда при создании VPC, иногда – EC2 интанса.
Продолжение тут>>>.