跳到主要内容
  1. Posts/

高枕无忧:Google Cloud Platform 基础

·

通过 GCP 认识云服务。

云计算是什么? #

  1. 可以在任何时间自助地获取计算资源,无需人工干预;
  2. 可以在任何地点访问这些计算资源;
  3. 云服务商拥有计算资源池,并从池中分配资源给用户;
  4. 计算资源可以弹性收缩;
  5. 按量计费,停止使用即停止收费。

GCP 地域和区域 #

地域(Zone)是一块 GCP 资源的部署区,不过不一定是一个类似数据中心的单一的建筑。若干个地域组成了区域(Region),同一区域内的不同地域之间网络通信速度极快。可以认为,一个地域就是一个区域内的故障域。为了提高容灾性能,可以进行多地域部署。

更进一步,为了防止类似自然灾害等不可抗力造成的数据损失,还可以进行多区域部署(区域之间至少相隔 160 km)。

GCP 资源层级树 #

图 1|资源层级树

每个 GCP 计算资源(Resource)属于且仅属于一个项目(Project)。若干个项目可以组成文件夹(Folder),而文件夹通过层级树结构(和文件系统类似)从属于一个组织(Organization)。创建文件夹和组织并不是必须的,但创建文件夹前需要先创建组织。

Project 标识符 #

标识符唯一性标识符来源可变性
Project ID全局唯一用户可指定不可变
Project name无需唯一用户可指定可变
Project number全局唯一GCP 分配不可变

IAM 策略 #

IAM 策略规定了:

  • 对哪些资源
  • 可以做什么

其中,“谁” 部分可以针对:

  • Google 账号
  • Google 群组
  • 服务账号
  • G Suite
  • Cloud Identity Domain

“对哪些资源” 部分比较简单,就是上面提到的任何资源节点(Resource / Project / Folder / Organization, etc.)。

“可以做什么” 部分由 IAM 角色定义。 IAM 角色是一系列权限的集合,可以分为三种角色:

  • Primitive Role 只能应用到整个 Project,分为 Owner / Editor / Viewer / Billing administrator 四个角色,所拥有的权限显而易见;
  • Predefined Role 是 GCP 服务中预定义的一些角色,可以应用到 Resource / Project / Folder / Organization 层甚至是某个资源实例上,粒度更细。
  • Custom Role 只能应用到 Project 或 Organization,由用户自定义,粒度较 Predefined Role 更细。

如果要授予权限给某个计算资源而不是一个用户,就需要针对该计算资源创建一个服务账号,将权限授予该服务账号。同时,服务账号本身也是一种 GCP 资源,因此 IAM 策略也可以应用到服务账号上,实现对服务账号本身的管理。

策略继承 #

IAM 策略可以应用到任何资源节点,并且会自顶向下继承。比较反直觉的是,当顶层策略和底层策略冲突时,两者中更宽松的策略会生效。

  • 🌰 1️⃣
    • Project 层策略规定某用户对某资源拥有修改权限
    • Organization 层策略规定该用户对该资源仅拥有读取权限
    • 前者更宽松,因此生效
  • 🌰 2️⃣
    • Project 层策略规定某用户对某资源拥有修改权限
    • Resource 层策略规定该用户对该资源仅拥有读取权限
    • 前者更宽松,因此生效

可以看到,发生冲突时,一个 IAM 策略是否生效与其所在层级无关,仅与其是否更为宽松有关。

云上虚拟机 #

Virtual Private Cloud Network #

VPC 用于在虚拟机(Compute Engine)之间构建网络,例如进行网段划分、防火墙设置、静态路由设置等。值得注意的是,VPC 是全局资源,是可以跨区域的,而 VPC 中创建的子网也可以跨地域。

类似物理网络,VPC 会维护一个路由表用于在虚拟机之间寻找路由,VPC 之间也可以互联。此外,VPC 还提供了分别针对区域内、外部流量的负载均衡、DNS 服务、CDN 服务等等。

Compute Engine 实践 #

  1. 在 Compute Engine 里创建新的 VM instance,命名为 my-vm-1,允许 HTTP 入站流量。
  2. 由于 my-vm-1 在 us-central1-a 地域中,我们在 Cloud Shell 中查找同区域内有哪些地域:
gcloud compute zones list | grep us-central1
  1. 随意选一个不同的地域,例如 us-central1-b,并修改当前地域:
gcloud config set compute/zone us-central1-b
  1. 创建第二个虚拟机:
gcloud compute instances create "my-vm-2" \
--machine-type "n1-standard-1" \
--image-project "debian-cloud" \
--image-family "debian-10" \
--subnet "default"
  1. 退出 Cloud Shell,SSH 到 my-vm-2,然后 ping 一下 my-vm-1,注意主机名:
ping my-vm-1.us-central1-a
  1. 在 my-vm-2 上连接 my-vm-1:
ssh my-vm-1.us-central1-a
  1. 在 my-vm-1 里上线一个网页并测试:
sudo apt-get install nginx-light -y
sudo vim /var/www/html/index.nginx-debian.html
curl http://localhost
  1. 退出 SSH 回到 my-vm-2,访问 my-vm-1 上的网页:
curl http://my-vm-1.us-central1-a/

云上存储 #

Cloud Storage #

常见的对象存储,上传文件,返回一个唯一的 URL。上传的文件按桶(bucket)组织,一旦上传便不可修改(但可以更新),访问权限则由 Cloud IAM 或更细粒度的 ACL 来控制。

图 2|Cloud Storage Classes

Cloud Bigtable & Cloud Datastore #

Cloud Bigtable 提供存储大量数据的 NoSQL 数据库服务,因为采用 key-value 对存储所以也可以当持久化的哈希表来用。可以通过开源的 HBase API 访问,因此也兼容 Apache Hadoop 生态。

Cloud Datastore 则是应用特化型的 NoSQL,区别主要在于对交易和类 SQL 查询的支持。当然,最重要的是有每日免费用量。

Cloud SQL & Cloud Spanner #

Cloud SQL 提供基于 MySQL 或 PostgreSQL 的 SQL 数据库服务,并配有冗余备份、容灾恢复等功能。而 Cloud Spanner 则可以认为是高配版的 Cloud SQL,在数据一致性和可用性方面都更优秀。

对比 #

图 3|GCP 存储服务对比

BigQuery 主要用于数据处理而不是数据存储,会在下文介绍。

Cloud Storage & Cloud SQL 实践 #

  1. 在 Compute Engine 里创建新的 VM instance,命名为 blogpost,允许 HTTP 入站流量,并在启动脚本中安装服务器:
apt-get update
apt-get install apache2 php php-mysql -y
service apache2 restart
  1. 在 Cloud Shell 中创建 Cloud Storage,注意 bucket 名称需要唯一,可以用 Project ID 来确保这一点:
gsutil mb -l US gs://$DEVSHELL_PROJECT_ID
  1. 从另一个桶中复制一张图片到 Cloud Shell:
gsutil cp gs://cloud-training/gcpfci/my-excellent-blog.png my-excellent-blog.png
ls
  1. 从 Cloud Shell 复制图片到新创建的桶:
gsutil cp my-excellent-blog.png gs://$DEVSHELL_PROJECT_ID/my-excellent-blog.png
  1. 检查是否成功:
gsutil ls gs://$DEVSHELL_PROJECT_ID
  1. 在控制台创建和 blogpost 同区域的 Cloud SQL,命名为 blog-db,并设置 root 密码;创建完毕后,新建一个用户,设置用户名和密码。
  2. 接下来,要让我们的 blog-db 只能被 blogpost 访问。为此,先查看 blogpost 的公网 IP,然后在 blog-db 配置面板的 Connections 选项卡里新建一个 Authorized Network,并填入这个 IP。由于要求 CIDR 格式而我们只想要单个机器能访问,填入 x.x.x.x/32 即可。
  3. 随后要让 blogpost 去使用 blog-db。SSH 到 blogpost,编写 /var/www/html/index.php
<html>
<head><title>Welcome to my excellent blog</title></head>
<body>
<h1>Welcome to my excellent blog</h1>
<?php
 $dbserver = "CLOUDSQLIP";
$dbuser = "blogdbuser";
$dbpassword = "DBPASSWORD";
// In a production blog, we would not store the MySQL
// password in the document root. Instead, we would store it in a
// configuration file elsewhere on the web server VM instance.
$conn = new mysqli($dbserver, $dbuser, $dbpassword);
if (mysqli_connect_error()) {
        echo ("Database connection failed:" . mysqli_connect_error());
} else {
        echo ("Database connection succeeded.");
}
?>
</body></html>
  1. 重启 apache2,访问 blogpost 的公网 IP,检查数据库连接。
  2. 接下来把之前那张图片加到网站上。在控制台 Storage -> Cloud Storage -> Browser 里找到图片,勾选 Share publicly 从而获得一个 URL(或者运行下面的命令)。随后在原来的 html 里插入图片即可。
gsutil acl ch -u allUsers:R gs://$DEVSHELL_PROJECT_ID/my-excellent-blog.png
  1. 重复第 9 步。

云上容器 #

也就是 Google Kubernetes Engine,后面单独开篇博客写。

云上应用 #

在 Compute Engine 中,用户自己选择虚拟机作为运行应用的基础设施;到了 Kubernetes Engine,这个基础设施变成了容器。但如果我们只是想快速部署一个应用,根本不想关心基础设施呢?这就是 App Engine 的作用。

App Engine 提供了类似 NoSQL 数据库、负载均衡、日志记录、用户认证、自动伸缩等服务,用户只需要关心业务代码、以及如何在代码中调用这些服务。在 Standard 模式中,因为提供了免费日限额,只要应用流量不太大就相当于永久免费使用 App Engine 服务。

Standard 模式运行在沙箱中,因此存在一些限制:

  • 不能向文件系统写文件,数据持久化必须通过数据库
  • 任意网络请求最大超时时间为 60 秒
  • 安装第三方软件也会受到限制

不过,Standard 模式只支持 Java、Python、PHP 和 Go 的 SDK,其他语言则需要使用 Flexible 模式。

Flexible 模式不受沙箱限制,因为这种模式实际上是在 Compute Engine 上运行用户自定义的容器。这会导致启动速度变慢,但应用对底层的访问更宽松,当然价格上也不存在免费额度了。

图 4|App Engine 两种模式对比

App Engine 实践 #

  1. 克隆示例应用:
git clone https://github.com/GoogleCloudPlatform/appengine-guestbook-python
cd appengine-guestbook-python
  1. app.yaml 中存储了应用的部署配置,可以先在本地运行起来测试下:
dev_appserver.py ./app.yaml
  1. 用 Cloud Shell 的 Preview 功能查看应用。
  2. 确认没有问题后进行部署:
gcloud app deploy ./index.yaml ./app.yaml

云上开发、部署与监控 #

云上开发 #

  • Cloud Source Repositories,也就是 GCP 中的 Git Repositories,优势在于和 GCP Project 以及其他产品的融合
  • Cloud Functions,也就是 GCP 中的云函数,这种方式目前可以说是对一个应用而言最高层面的抽象
  • Cloud Endpoint,也就是 GCP 中用于维护 API 的服务

图 5|应用部署抽象层级的对比

云上部署 #

  • Deployment Manager 提供了声明式的方式来设定部署环境,有点像 Kubernetes deployment,也可以把设定文件放在 Cloud Source Repositories 里

云上监控 #

  • Stackdriver 用于监控云上资源,没有发现什么有特色的地方?

云上部署与监控实践 #

  1. 准备环境,下载 Deployment Manager 的模版:
export MY_ZONE=us-central1-a
gsutil cp gs://cloud-training/gcpfcoreinfra/mydeploy.yaml mydeploy.yaml
  1. 替换模版中的字段:
sed -i -e "s/PROJECT_ID/$DEVSHELL_PROJECT_ID/" mydeploy.yaml
sed -i -e "s/ZONE/$MY_ZONE/" mydeploy.yaml
  1. 最终模版大约是这样的:
resources:
  - name: my-vm
    type: compute.v1.instance
    properties:
      zone: us-central1-a
      machineType: zones/us-central1-a/machineTypes/n1-standard-1
      metadata:
        items:
          - key: startup-script
            value: "apt-get update"
      disks:
        - deviceName: boot
          type: PERSISTENT
          boot: true
          autoDelete: true
          initializeParams:
            sourceImage: https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-9-stretch-v20180806
      networkInterfaces:
        - network: https://www.googleapis.com/compute/v1/projects/qwiklabs-gcp-dcdf854d278b50cd/global/networks/default
          accessConfigs:
            - name: External NAT
              type: ONE_TO_ONE_NAT
  1. 部署:
gcloud deployment-manager deployments create my-first-depl --config mydeploy.yaml
  1. 查看已部署的 Compute Engine。
  2. 编辑模版中的 startup script,更新为:
value: "apt-get update; apt-get install nginx-light -y"
  1. 执行更新:
gcloud deployment-manager deployments update my-first-depl --config mydeploy.yaml
  1. 检查 Compute Engine 中新的 startup script。
  2. 停止虚拟机,设置 Service account 为 Compute Engine default service accountAllow full access to all Cloud APIs。启动虚拟机。
  3. SSH 到虚拟机,运行如下命令增加 CPU 负载:
dd if=/dev/urandom | gzip -9 >> /dev/null &
  1. 控制台中为 Project 开启 Monitoring Workspace(自动),随后在虚拟机中安装 agent:
curl -sSO https://dl.google.com/cloudagents/install-monitoring-agent.sh
sudo bash install-monitoring-agent.sh
curl -sSO https://dl.google.com/cloudagents/install-logging-agent.sh
sudo bash install-logging-agent.sh
  1. 控制台 Monitoring 面板中点击 Metrics Explorer -> Metric,选择虚拟机资源和 CPU 使用情况并查看图表。
  2. 运行 kill %1 停止占用 CPU,再次查看图表。

云上数据处理 #

  • Cloud Dataproc,用于在 GCP 上运行 Hadoop、Spark、Hive、Pig 等数据集群
  • Cloud Dataflow,用于构建数据流水线,提供了资源自动伸缩的功能,相比 Cloud Dataproc 更灵活
  • BigQuery,顾名思义,提供针对大量数据提供高速 SQL 查询服务
  • Cloud Pub/Sub,提供可靠的、多对多的异步消息推送 / 拉取服务
  • Cloud Datalab,也就是 GCP 中的 Jupyter Notebook,底层基础设施使用的是 BigQuery、Compute Engine 和 Cloud Storage
  • Cloud ML,也就是在 GCP 上运行 TensorFlow,好处是可以利用 GCP 上的高性能计算资源

BigQuery 实践 #

  1. 在 BigQuery 中新建数据集 logdata,随后创建表 accesslog,数据源来自 Cloud Storage,URL 为 gs://cloud-training/gcpfci/access_log.csv
  2. 创建完成后,在表详情页面可以 Preview 一些数据。
  3. 在控制台运行 query:
select int64_field_6 as hour, count(*) as hitcount from logdata.accesslog
group by hour
order by hour
  1. 类似上一步的查询也可以用 bq 命令行工具完成:
bq query "select string_field_10 as request, count(*) as requestcount from logdata.accesslog group by request order by requestcount desc"

Network 和 Subnetwork #

Network 是跨 Region 的,拥有自己的 DNS。处于同一 Network 的虚拟机之间,即使处于不同 Region,也可以通过内网 IP 互相通信。同理,同一 Region 中的虚拟机,如果不处于同一 Network,就无法通过内网 IP 通信。

同理,Subnetwork 是跨 Zone 的。处于同一 Subnetwork 的虚拟机之间,即使处于不同 Zone,也可以通过内网 IP 通信。Subnetwork 实际上就是通常意义下的子网,也就是 RFC 1918。Subnetwork 只能扩展不能缩小。

DNS #

Network 内部的 DNS 是为了确保虚拟机内部 IP 变化时,对虚拟机的访问不受影响。这一点和 K8s 如出一辙。至于 IP 地址、路由,也和通常意义下的差不多。

防火墙 #

每个 VPC 实际上就是一个分布式防火墙,只不过出入控制是虚拟机级的。也就是说,不仅整个网络受到防火墙保护,每个虚拟机也是如此。这使得防火墙规则也可以针对每个虚拟机进行不同设置。

最后,保底规则是拒绝全部 Ingress 请求,允许全部 Egress 请求。防火墙规则也遵循上文提到的资源层级树层层继承。

多网卡 #

每个虚拟机在创建时可以指定多个网卡,从而接入多个不同的 Network。不过,Network 内部的 DNS 只能解析到 nic0 也就是第一个网卡,如果 nic0 并不对应该 Network,DNS 解析会失效。

多网络 #

Shared VPC 可以连接多个不同 Project 的计算资源,使得计算资源之间可以通过内网 IP 通信。类似地,VPC Network Peering 可以跨 Organiztion 连接计算资源,实现点对点的连接。两者最大的区别在于,网络管理是否是中心化的。

Shared VPCVPC Network Peering
跨 Organization
连接同一 Project 内的资源
网络管理模式中心化去中心化

负载均衡 #

负载均衡是基于虚拟机实例组的,类似于 K8s 里的一个 ReplicaSet,甚至也包含了自动伸缩、滚动更新、健康检查等功能。一个虚拟机实例组一般在同一 Region 内。

HTTP(S) 负载均衡器将用户请求发送至 HTTP(S) 代理,随后转发给 backend service,最终发送到不同 Region 的实例组。对于非 HTTP 请求,则可以使用 TCP 和 SSL 负载均衡器。如果需要发送 UDP 请求或者 TCP 和 SSL 负载均衡器不支持的请求,则可以使用适用范围更广的 Network 负载均衡器。最后,如果服务不需要对公网开放,则可以使用同样支持 TCP / UDP 请求,但速度更快、配置更简单的内网负载均衡器(基于 Andromeda)。

可以通过如下流程图来选择合适的负载均衡器:

图 6|选择合适的负载均衡器