技巧90 使用OpenShift在本地运行AWS API

本地开发最大的挑战之一是针对其他服务测试应用程序。如果可以将服务放在容器中,则Docker可以提供帮助,但在外部第三方服务的庞大世界中这是尚未解决的问题。

常见的解决方案是拥有测试API实例,但是这些实例通常会提供假响应——如果围绕服务构建应用程序,则无法进行更完整的功能测试。例如,假设你想将AWS S3用作应用程序的上传位置,然后在该位置上处理应用程序——对此进行测试会花钱。

问题

想要在本地使用类似AWS的API进行开发。

解决方案

设置LocalStack并使用可用的AWS服务替代物。

在本演练中,我们将使用Minishift设置OpenShift系统,然后在其pod中运行LocalStack。OpenShift是由RedHat赞助的对Kubernetes的包装,它提供了更适合Kubernetes企业生产环境部署的额外功能。

在本技巧中,我们将介绍:

  • OpenShift中路由的创建;
  • 安全上下文约束;
  • OpenShift和Kubernetes之间的区别;
  • 使用公共Docker镜像测试AWS服务。

注意

要学习本技巧,需要安装Minishift。Minishift和在技巧89中所见的Minikube类似。不同之处在于,它包含了对OpenShift的安装(在技巧99中详细解释)。

1.LocalStack

LocalStack是一个旨在为开发者提供尽可能完整的一组AWS API的项目,依赖这些API开发不会产生任何费用。这对于在真正花费时间和金钱之前针对AWS进行测试或尝试编码非常有用。

LocalStack在本地机器上启动以下核心Cloud API:

LocalStack支持在Docker容器中或本机上运行。它是基于Moto构建的,而Moto是基于Boto构建的模拟框架,而Boto又是Python AWS开发工具包。

在OpenShift集群中运行使我们能够运行许多AWS API环境。然后,我们就可以为每组服务创建不同的端点,并将它们彼此隔离。另外,我们可以减少对资源使用的担心,因为集群调度程序将解决这一问题。但是,LocalStack并不是开箱即用的,因此我们将指导读者完成需要完成的操作。

2.确保Minishift安装好了

至此,我们假设读者已经设置好了Minishift(读者可以查看其有关入门的官方文档)。检查Minishift是否安装正确的方法如代码清单12-4所示。

代码清单12-4 检查Minishift安装正确

$ eval $(minishift oc-env)
$ oc get all
No resources found.
3.更改默认安全上下文约束

安全上下文约束(security context constraints,SCC)是OpenShift概念,允许对Docker容器的功能进行更细粒度的控制。安全上下文约束控制SELinux上下文(见技巧100),可以从正在运行的容器中删除功能(见技巧93),可以确定pod可以作为哪个用户运行,等等。

为了使它运行,我们需要更改默认的 restricted (受限的)SCC。读者也可以创建一个单独的SCC,并将其应用于特定项目,读者可以自己尝试。

要更改“受限的”SCC,我们需要成为集群管理员:

$ oc login -u system:admin

然后可以通过下列命令编辑“受限的”SCC:

$ oc edit scc restricted

我们会看到 restricted SCC的定义。

此时我们必须要做的两件事情是:

  • 允许容器作为任意用户运行(本例中是 root );
  • 防止SCC把我们的能力限制在 setuidsetgid
4.允许作为任意用户运行

默认情况下,LocalStack容器以root身份运行,但是出于安全原因,OpenShift不允许容器默认以root身份运行。相反,它会在非常高的范围内选择一个UID,并以此UID身份运行。注意,UID是数字,与用户名不同,用户名是映射到UID的字符串。

为了简化问题,并允许LocalStack容器以root身份运行,将

runAsUser:
 type: MustRunAsRange

改为

runAsUser:
 type: RunAsAny

这让容器可以作为 任意 用户运行,而不是作为UID范围内的一个用户运行。

5.允许SETUID和SETGID的能力

当LocalStack启动时,它需要成为另一个用户才能启动ElastiCache。ElastiCache服务无法以root用户身份启动。

为了解决这个问题,使用LocalStack的 su 命令作为向容器中的LocalStack用户发送的启动命令。由于受限的SCC明确禁止更改用户ID或组ID的操作,因此我们需要删除这些限制。为此,要删除以下几行:

- SETUID
- SETGID
6.保存文件

完成了前面两步,就该保存文件了。

记下宿主机。如果执行下面的命令,可以获得本地机器可访问的Minishift实例:

$ minishift console --machine-readable | grep HOST | sed 's/^HOST=\(.*\)/\1/'

记下这一宿主机,后面需要替换。

7.部署pod

部署LocalStack只需要简单执行下面的命令:

$ oc new-app localstack/localstack --name="localstack"

这将获取localstack/localstack镜像并围绕它创建一个OpenShift应用程序,设置内部服务(基于LocalStack Docker镜像的Dockerfile中公开的端口),在pod中运行该容器,并执行其他各种管理任务。

8.创建路由

如果要从外部访问服务,则需要创建OpenShift路由,该路由会创建用于访问OpenShift网络中的服务的外部地址。例如,要为SQS服务创建路由,就要创建代码清单12-5所示的文件,称为route.yaml。

代码清单12-5 route.yaml

apiVersion: v1  ⇽--- 在yaml文件的顶部指定了Kubernetes API版本
 kind: Route  ⇽--- 创建的对象类型指定为Route
 metadata:   ⇽--- 元数据部分包含有关路由的信息,而不是路由本身的规范
   name: sqs  ⇽--- 在此为路由命名
 spec:   ⇽---  spec部分指定路线的详细信息
   host: sqs-test.HOST.nip.io  ⇽---  host是路由将被映射到的URL,即客户端访问的URL
   port:   ⇽--- 
     targetPort: 4576-tcp  ⇽---  port部分在to部分中指定的服务上标识路由将到达的端口
   to:   ⇽---  to部分标识将请求路由到的位置
     kind: Service  ⇽--- 
     name: localstack  ⇽--- 在本例中,它起源于LocalStack服务

通过执行下面的命令创建路由:

$ oc create -f route.yaml

这会创建刚才创建的yaml文件描述的路由。然后对每个想要设置的服务重复这一过程。

然后执行 oc get all 来查看刚才在OpenShift项目里创建了什么:

$ oc get all  ⇽--- 返回OpenShift项目中最重要的项目
 NAME DOCKER REPO TAGS UPDATED  ⇽--- 
 is/localstack 172.30.1.1:5000/myproject/localstack latest 15 hours ago  ⇽--- 首先列出的是镜像流。这些是跟踪本地或远程镜像状态的对象
 NAME REVISION DESIRED CURRENT TRIGGERED BY  ⇽--- 
 dc/localstack 1 1 1 config,image(localstack:latest)   ⇽--- 接下来列出部署配置,这些配置指定了将pod部署到集群的方式
 NAME DESIRED CURRENT READY AGE  ⇽--- 
 rc/localstack-1 1 1 1 15  ⇽--- 第三类是复制配置,它指定正在运行的Pod的复制特征
 NAME HOST/PORT PATH SERVICES PORT TERMINATION WILDCARD  ⇽--- 第四类是在项目中设置的路由
 routes/sqs sqs-test.192.168.64.2.nip.io localstack 4576-tcp None
 NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE  ⇽--- 
 svc/localstack 172.30.187.65 4567/TCP,4568/TCP,4569/TCP,4570/TCP,4571/TCP,4572/TCP,4573/TCP,4574/TCP,4575/TCP,4576/TCP,4577/TCP,4578/TCP,4579/TCP,4580/TCP,4581/TCP,4582/TCP,8080/TCP 15h  ⇽--- 列出的下一类是服务。在这里,可以看到Dockerfile中公开的端口会使得该服务公开端口
 NAME READY STATUS RESTARTS AGE  ⇽--- 
 po/localstack-1-hnvpw 1/1 Running 0 15h  ⇽--- 最后,列出了项目中的pod

尽管从技术上来讲, oc get all 命令显示的并不是项目中可用的 所有 对象,但是它显示了对运行应用程序最重要的项目。

现在就可以将类似于SQS的AWS服务作为URL端点进行访问,以对我们的代码进行测试了。

9.访问服务

现在,我们可以从宿主机上访问这一服务。下面是创建SQS流的示例:

 $ aws --endpoint-url=http://kinesis-test.192.168.64.2.nip.io kinesis
➥ list-streams  ⇽---  aws客户端应用程序用于访问新创建的网络接口,并要求kinesis列出其流
 {  ⇽--- 
  "StreamNames": []
 }  ⇽---  JSON输出显示不存在流
 $ aws --endpoint-url=http://kinesis-test.192.168.64.2.nip.io kinesis
➥ create-stream --stream-name teststream --shard-count 2  ⇽--- 再次调用aws客户端以创建名为teststream的SQS流,其分片计数为2
 $ aws --endpoint-url=http://kinesis-test.192.168.64.2.nip.io kinesis
➥ list-streams  ⇽--- 同样,您要求提供kinesis流列表
 {  ⇽--- 
  "StreamNames": [
  "teststream"
  ]
 }  ⇽---  JSON输出表明存在一个称为teststream的流

注意

我们需要安装 aws 客户端。另外,可以直接对API端点执行 curl 命令,但是我们不建议这样做。这样做还需要你已经执行 aws configure 并指定了你的AWS密钥和默认区域。指定的实际值与LocalStack无关,因为它不进行身份验证。

这里我们只介绍了一种服务,但是这一技巧很容易扩展到本技巧开头列举的其他项目中。

讨论

本技巧使我们了解了OpenShift(以及OpenShift所基于的Kubernetes)的强大功能。要使用可用端点启动有用的应用,并处理所有内部连接,在很多方面都是实现Docker提供的可移植性承诺,并将其纵向拓展到数据中心。

例如,可以更进一步,可以在同一OpenShift集群上部署多个LocalStack实例。可以并行进行针对AWS API的测试,而不必花费更多的资源(当然,这取决于OpenShift集群的大小和测试的需求)。因为这就是全部代码,所以可以设置持续集成以动态启动和关闭LocalStack实例,以便在每次AWS代码库提交的时候与之对话。

除指出了Kubernetes的各个方面之外,这一特殊技巧还证明了OpenShift之类的产品正在Kubernetes之上构建以扩展其功能。例如,安全上下文约束是一个OpenShift概念(尽管安全上下文也存在于Kubernetes中),“路由”是一个在Kubernetes之上创建的OpenShift概念,这一概念最终直接用于Kubernetes中的实现。随着时间的流逝,为OpenShift开发的功能已被Kubernetes所采用,并已成为其产品的一部分。

在技巧99中我们将再次看到OpenShift,到时候我们将研究如何将其用作平台,安全地让用户运行容器。

results matching ""

    No results matching ""