网易首页 > 网易号 > 正文 申请入驻

使用Kubernetes,一个人如何支撑起创业公司运作?

0
分享至

  选自Simon‘s blog

  作者:Anthony Simon

  机器之心编译

  编辑:杜伟、陈萍

  

一篇来自创业公司的技术分享,主要介绍了在 AWS 上使用 Kubernetes,从负载平衡到 cron 作业监控,再到支付和订阅。

  Kubernetes 是一款开源软件,你可以利用它大规模地部署和管理容器化应用程序。Kubernetes 管理 Amazon EC2 计算实例集群,并在这些实例上运行容器以及执行部署、维护与扩展进程。借助 Kubernetes,你可以在本地和云上使用相同的工具集运行任何类型的容器化应用程序。

  

  AWS 利用可扩展并且高度可用的虚拟机基础设施、具有社区支持的服务集成,以及经过认证的 Kubernetes 托管服务 Amazon Elastic Kubernetes Service (EKS),大幅简化了在云上运行 Kubernetes 的过程。

  来自哥斯达黎加的软件工程师 Anthony Najjar Simon(下文中均以作者代替)向我们分享了一个人如何经营运作一家公司。该公司建立在作者在德国的公寓里,完全由自己出资。他主要介绍了在 AWS 上使用 Kubernetes,从负载平衡到 cron 作业监控,再到支付和订阅,实现了一人公司的顺利运行。

  

  总体概览图

  基础设施可以同时处理多个项目,但为了说明问题,作者使用 SaaS Panelbear 作为这种设置的实际示例。

  

  Panelbear 中的浏览器计时图表。

  作者表示,从技术角度来看,这种 SaaS 每秒需要处理来自世界各地的大量请求,以高效的格式存储数据,以便进行实时查询;从业务角度来看,它还处于初级阶段(六个月前才开始推进),但发展速度很快,在预期范围内。

  然而,令人沮丧的是,作者不得不重新实现以前非常熟悉的工具:零停机部署、弹性伸缩、安全检查、自动 DNS / TLS / ingress 规则等。作者以前使用 Kubernetes 来处理更高层级的抽象概念,同时进行监控和保持灵活性。

  六个月过去了,历经几次迭代,目前的设置仍然是 Django monolith。作者现在使用 Postgres 作为应用程序数据库,ClickHouse 用于分析数据,Redis 用于缓存。作者还将 Celery 用于预期任务,并使用自定义事件队列缓冲数据写入,并在一个托管 Kubernetes 集群(EKS)上运行这些东西。

  

  高级架构概述。

  上述内容听起来可能很复杂,但实际上是一个在 Kubernetes 上运行的老式整体架构,并且用 Rails 或 Laravel 替换 Django。有趣的部分是如何将所有内容复合在一起并进行自动化,包括弹性伸缩、ingress、TLS 协议、失效转移、日志记录、监视等。

  值得注意的是,作者在多个项目中使用了这个设置,这有助于降低成本并非常轻松地启动实验(编写 Dockerfile 和 git push)。可能有人会问,这需要花费很多的时间,但实际上作者花很少的时间管理基础设施,通常每月只需花费 2 个小时以内的时间。其余大部分时间都花在开发特性、做客户支持和发展业务上。

  作者经常告诉朋友的一句话是:「Kubernetes 让简单的东西变得复杂,但它也让复杂的东西变得简单。」

  Automatic DNS,SSL,负载均衡

  作者在 AWS 上有一个托管 Kubernetes 集群,并在其中运行了各种项目。接下来开始本教程的第一站:如何将流量引入集群。该集群在一个私有网络中,无法从公共互联网直接访问它。

  

  流量在边缘缓存或者传达到操作的 AWS 区域。

  但是,Kubernetes 如何知道将请求转发到哪个服务呢?这就是 ingress-nginx 的作用所在。简而言之:它是一个由 Kubernetes 管理的 NGINX 集群,是集群内所有流量的入口点。

  NGINX 在将请求发送到相应的 app 容器之前,会应用速率限制和其他流量整形规则。在 Panelbear 的例子中,app 容器是由 Uvicorn 提供服务的 Django。

  它与 VPS 方法中的 nginx/gunicorn/Django 没有太大的不同,具有额外的横向缩放优势和自动 CDN 设置。大多数是 Terraform/Kubernetes 之间的一些文件,所有部署的项目都共享它。

  
apiVersion: networking.k8s.io/v1beta1kind: Ingressmetadata:namespace: examplename: example-apiannotations:kubernetes.io/ingress.class: "nginx"nginx.ingress.kubernetes.io/limit-rpm: "5000"cert-manager.io/cluster-issuer: "letsencrypt-prod"external-dns.alpha.kubernetes.io/cloudflare-proxied: "true"spec:tls:- hosts:- api.example.comsecretName: example-api-tlsrules:- host: api.example.comhttp:paths:- path: /backend:serviceName: example-apiservicePort: http

  自动 rollout 和回滚

  

  提交新 commit 时发生的反应链。

  就 application repo 而言,该 app 新版本已测试过,并准备作为 Docker 镜像部署:

  
panelbear/panelbear-webserver:6a54bb3

  接下来怎么做?有了新的 Docker 镜像,但没有部署?Kubernetes 集群有一个叫做 flux 的组件,它会自动同步集群中当前运行的内容和 app 的最新图像。

  

  Flux 自动跟踪基础架构 monorepo 中的新版本。

  当有了新的 Docker 镜像可用时,Flux 会自动触发增量卷展栏(incremental rollout),并在 Infrastructure Monrepo 中记录这些操作。

  可以将此 monorepo 视为可部署的文档,但稍后将详细介绍。

  水平自动伸缩

  该 app 容器基于 CPU / 内存使用进行自动扩展。Kubernetes 尝试在每个节点上打包尽可能多的工作负载,以充分利用它。

  如果集群中每个节点有太多的 pod,则将自动生成更多的服务器以增加集群容量并减轻负载。类似地,当没有太多事情发生时,它也会缩小。

  

  在本例中,它将根据 CPU 使用情况自动调整 panelbear api pod 的数量,从 2 个副本开始,但上限为 8 个。

  CDN 静态资产缓存

  在为 app 定义 ingress 规则时,标注「cloudflare-proxied: "true"」通知 Kubernetes 使用 cloudflare 进行 DNS,并通过 CDN 和 DDoS 保护代理所有请求。

  之后在使用中,只需在应用程序中设置标准的 HTTP 缓存头,以指定可以缓存哪些请求以及缓存多长时间。

  
# Cache this response for 5 minutesresponse["Cache-Control"] = "public, max-age=300"

  Cloudflare 将使用这些响应头来控制边缘服务器上的缓存行为。对于这样一个简单的设置,它工作得非常好。

  作者使用 Whitenoise 直接从应用程序容器提供静态文件。这样就避免了每次部署都需要将静态文件上传到 Nginx/Cloudfront/S3。到目前为止,它工作得非常好,大多数请求在被填满时都会被 CDN 缓存。它的性能,并保持简单的事情。

  作者还将 NextJS 用于一些静态网站,例如 Panelbear 的登录页。可以通过 Cloudfront/S3 甚至 Netlify 或 Vercel 提供服务,但是在集群中作为一个容器运行它并让 Cloudflare 缓存请求的静态资产是很容易的。这样做没有额外的成本,而且可以重用所有工具进行部署、日志记录和监视。

  应用程序数据缓存

  除静态文件缓存之外,作者还需要应用程序数据缓存(如繁重计算的结果、Django 模型、速率限制计数器等)。

  作者的定价计划基于每月的分析事件。为此,有必要进行某种计量,以了解在当前计费周期内消耗了多少事件,并强制执行限制。不过,作者不会在顾客超限时立即中断服务。相反,系统会自动发送一封容量耗尽的电子邮件,并在 API 开始拒绝新数据之前给客户一个宽限期。

  因此,对于这个特性,有一个应用上述规则的函数,它需要对 DB 和 ClickHouse 进行多次调用,但需要缓存 15 分钟,以避免每次请求都重新计算。优点是足够好和简单。值得注意的是:计划更改时缓存会失效,升级也可能需要 15 分钟才能生效。

  
@cache(ttl=60 * 15)def has_enough_capacity(site: Site) -> bool:"""Returns True if a Site has enough capacity to accept incoming events,or False if it already went over the plan limits, and the grace period is over."""

  单点限速

  虽然作者在 Kubernetes 上的 nginx-ingress 强制执行全局速率限制,但同时希望在每个端点 / 方法的基础上实施更具体的限制。

  为此,作者使用 Django Ratelimit 库来轻松地声明每个 Django 视图的限制,使用 Redis 作为后端来跟踪向每个端点发出请求的客户端(其存储基于客户端密钥的哈希,而不是基于 IP)。例如:

  

  在上面的示例中,如果客户端试图每分钟向这个特定的端点 POST 超过 5 次,那么后续的调用将使用 HTTP 429 Too Many Requests 状态码拒绝。

  

  当被限速时,使用者会收到友好的错误信息。

  应用程序管理

  Django 可以为所有模型免费提供了一个管理面板。它是内置的,非常方便用于检查数据以进行客户支持工作。

  

  Django 内置的管理面板对客户支持非常有用。

  作者添加了一些操作来管理来自 UI 的东西,比如阻止访问可疑账户、发送公告邮件等。安全方面:只有员工用户可以访问面板,并为所有账户计划添加 2FA 作为额外安全保障。

  此外,每次用户登录时,作者都会自动向帐户的电子邮件发送一封安全电子邮件,其中包含新会话的详细信息。现在作者在每次新登录时都会发送它,但将来可能会更改它以跳过已知设备。

  

  运行调度工作

  另一个有趣的用例是,作为 SaaS 的一部分,作者运行了许多不同的调度作业。这些工作包括为客户生成每日报告、每 15 分钟计算一次使用情况、发送员工电子邮件等。

  这个设置实际上很简单,只需要几个 Celery workers 和一个 Celery beat scheduler 在集群中运行。它们被配置为使用 Redis 作为任务队列。

  当计划任务未按预期运行时,作者希望通过 SMS/Slack/Email 获得通知。例如,当每周报告任务被卡住或严重延迟时,可以使用 Healthchecks.io,但同时也检查 Cronitor 和 CronHub。

  

  来自 Healthchecks.io 的 cron 作业监控仪表板。

  为了抽象 API,作者写了一个 Python 代码片段来自动创建监控器和状态提示:

  
def some_hourly_job():# Task logic
# Ping monitoring service once task completesTaskMonitor(name="send_quota_depleted_email",expected_schedule=timedelta(hours=1),grace_period=timedelta(hours=2),).ping()

  App 配置

  所有应用程序都是通过环境变量配置的,虽然老式但很便携,而且具有良好支持。例如,在 Django settings.py 中,作者会用一个默认值设置一个变量:

  
INVITE_ONLY = env.str("INVITE_ONLY", default=False)

  如以下代码:

  
from django.conf import settings# If invite-only, then disable account creation endpointsif settings.INVITE_ONLY:

  可以重写 Kubernetes configmap 中的环境变量:

  
apiVersion: v1kind: ConfigMapmetadata:namespace: panelbearname: panelbear-webserver-configdata:INVITE_ONLY: "True"DEFAULT_FROM_EMAIL: "The Panelbear Team "SESSION_COOKIE_SECURE: "True"SECURE_HSTS_PRELOAD: "True"SECURE_SSL_REDIRECT: "True"

  加密

  作者使用 Kubernetes 中的 kubeseal 组件,它使用非对称加密来加密,只有授权访问解密密钥的集群才能解密。如下代码所示:

  

  集群将自动解密,并将其作为环境变量传递给相应的容器:

  
DATABASE_CONN_URL='postgres://user:pass@my-rds-db:5432/db'SESSION_COOKIE_SECRET='this-is-supposed-to-be-very-secret'

  为了保护集群中的隐私,作者通过 KMS 使用 AWS 管理的加密密钥。 在创建 Kubernetes 集群时,这是一个单独的设置,并且它是完全受管理的。

  对于实验,作者在集群中运行原版 Postgres 容器,并运行每日备份到 S3 的 Kubernetes cronjob。随着项目进展,对于 Panelbear 等,作者将数据库从集群转移到 RDS 中,让 AWS 负责加密备份、安全更新等操作。

  为了增加安全性,AWS 管理的数据库仍然部署在作者的专用网络中,因此它们无法通过公共互联网访问。

  作者依靠 ClickHouse 对 Panelbear 中的分析数据进行高效存储和实时查询。这是一个非常棒的列式数据库,速度非常快,当将数据组织得很好时,你可以获得高压缩比(存储成本越低 = 利润率越高)。

  目前,作者在 Kubernetes 集群中自托管了一个 ClickHouse 实例。作者有一个 Kubernetes CronJob,它定期地将所有数据以高效的列格式备份到 S3。在灾难恢复(disaster recovery)的情况下,作者使用几个脚本来手动备份和恢复 S3 中的数据。

  基于 DNS 的服务发现

  除了 Django,作者还运行 Redis、ClickHouse、NextJS 等容器。这些容器必须以某种方式相互通信,并通过 Kubernetes 中的内置服务发现(service discovery)来实现。

  很简单:作者为容器定义了一个服务资源,Kubernetes 自动管理集群中的 DNS 记录,将流量路由到相应的服务。例如,给定集群中公开的 Redis 服务:

  

  可以通过以下 URL 从集群的任何位置访问此 Redis 实例:

  
redis://redis.weekend-project.svc.cluster:6379

  注意:服务名称和项目命名空间是 URL 的一部分。这使得所有集群服务都可以很容易地实现互通信。下图展示了作者如何通过环境变量配置 Django,用来使用集群中的 Redis:

  

  Kubernetes 将自动保持 DNS 记录与 pod 同步,即使容器在自动伸缩期间跨节点移动。

  版本控制基础架构

  作者希望通过一些简单的命令来创建和销毁版本控制、可复制的基础架构。为了实现这一点,作者在 monorepo(包含 all-things 架构) 中使用 Docker、Terraform 和 Kubernetes manifests,甚至在跨项目中也如此。对于每个应用程序 / 项目,作者都使用一个单独的 git repo。

  作者通过在 git repo 中描述基础架构,不需要跟踪某些 obscure UI 中的每个小资源和配置设置。这样能够在灾难恢复时使用一个命令还原整个堆栈。下面是一个示例文件夹结构,在 infra monorepo 上可能找到的内容:

  
# Cloud resourcesterraform/aws/rds.tfecr.tfeks.tflambda.tfs3.tfroles.tfvpc.tfcloudflare/projects.tf
# Kubernetes manifestsmanifests/cluster/ingress-nginx/external-dns/certmanager/monitoring/
apps/panelbear/webserver.yamlcelery-scheduler.yamlcelery-workers.yamlsecrets.encrypted.yamlingress.yamlredis.yamlclickhouse.yamlanother-saas/my-weekend-project/some-ghost-blog/
# Python scripts for disaster recovery, and CItasks/
# In case of a fire, some help for future meREADME.mdDISASTER.mdTROUBLESHOOTING.md

  这种设置的另一种优势是,所有的移动部件都在同一个地方描述。作者可以配置和管理可重用的组件,如集中式日志记录、应用程序监控和加密机密等。

  云资源 Terraform

  作者采用 Terraform 来管理大多数底层云资源,这可以帮助记录和跟踪组成基础设施的资源和配置。在错误恢复时,作者可以使用单个命令启动和回滚资源。

  例如,如下是作者的 Terraform 文件之一,用于为加密备份创建一个私有 S3 bucket,该 bucket 在 30 天后过期:

  
resource "aws_s3_bucket" "panelbear_app" {bucket = "panelbear-app"acl = "private"
tags = {Name = "panelbear-app"Environment = "production"
lifecycle_rule {id = "backups"enabled = trueprefix = "backups/"
expiration {days = 30
server_side_encryption_configuration {rule {apply_server_side_encryption_by_default {sse_algorithm = "AES256"

  Kubernetes app 部署清单

  类似地,作者所有的 Kubernetes 清单都在基础设施 monorepo 中的 YAML 文件中描述,并将它们分为两个目录 cluster 和 apps。

  在 cluster 目录中,作者描述了所有集群范围的服务和配置,如 nginx-ingress、encrypted secrets、prometheus scrapers 等。这些基本上是可重用的比特。

  apps 目录在每个项目中包含一个命名空间,描述部署所需的内容,如 ingress rules、deployments、secrets、volumes 等。

  Kubernetes 的一个很酷的地方是:你可以定制几乎所有关于堆栈的东西。因此,如果你想使用可调整大小的加密 SSD volumes,则可以在集群中定义一个新的 StorageClass。Kubernetes 和 AWS 将协调产生作用,如下所示:

  

  现在,作者可以为任何部署附加这种类型的持久存储,Kubernetes 管理请求的资源:

  

  订购和支付

  作者采用 Stripe Checkout 来保存付款、创建结账屏幕、处理信用卡 3D 安全要求、甚至客户账单门户的所有工作。这些工作没有访问支付信息本身,这是一个巨大的解脱,可以专注于产品,而不是高度敏感的话题,如信用卡处理和欺诈预防。

  

  在 Panelbear 中的客户计费门户示例。

  现在需要做的就是创建一个新的客户会话,并将客户重定向到 Stripe 托管页面之一。然后,监听客户是否升级 / 降级 / 取消的网络钩子(webhook),并相应地更新数据库。

  当然,有一些重要的部分,比如验证网络钩子是否真的来自 Stripe。不过,Stripe 的文档很好地涵盖了所有要点。作者可以非常容易地在代码库中进行管理,如下所示:

  
# Plan constantsFREE = Plan(code='free',display_name='Free Plan',features={'abc', 'xyz'},monthly_usage_limit=5e3,max_alerts=1,stripe_price_id='...',
BASIC = Plan(code='basic',display_name='Basic Plan',features={'abc', 'xyz'},monthly_usage_limit=50e3,max_alerts=5,stripe_price_id='...',

PREMIUM = Plan(code='premium',display_name='Premium Plan',features={'abc', 'xyz', 'special-feature'},monthly_usage_limit=250e3,max_alerts=25,stripe_price_id='...',
# Helpers for easy accessALL_PLANS = [FREE, BASIC, PREMIUM]PLANS_BY_CODE = {p.code: p for p in ALL_PLANS}

  作者将 Stripe 应用在 API 端点、cron job 和管理任务中,以确定哪些限制 / 特性适用于特定的客户,当前计划用的是 BillingProfile 模型上的 plan_code。作者还将用户与帐单信息分开,因为计划在某个时间添加组织 / 团队,这样就可以轻松地将帐单配置文件迁移到帐户所有者 / 管理员用户。

  当然,如果你在电子商务商店中提供数千种单独的产品,这种模式是无法扩展的,但它对作者来说非常有效,因为 SaaS 通常只有几个计划。

  Logging

  作者不需要 logging agen 之类的东西测试代码,只需登录 stdout、Kubernetes,即可自动收集 log。你也可以使用 FluentBit 自动将这些 log 发送到 Elasticsearch/Kibana 之类的应用上,但为了保持简单,作者还没有这么做。

  为了检查 log,作者使用了 stern,这是一个用于 Kubernetes 的小型 CLI 工具,可以非常容易地跨多个 pod 跟踪应用程序 log。例如,stern -n ingress-nginx 会跟踪 nginx pod 的访问 log,甚至跨越多个节点。

  监控和告警

  最开始,作者采用一个自托管 Prometheus/Grafana 来自动监控集群和应用指标。然而,作者不喜欢自托管监控堆栈,因为在集群中一旦出现错误,那么告警系统也会随之崩溃。

  作者所有的服务都有 Prometheus 集成,该集成可自动记录指标并将指标转发到兼容的后端,例如 Datadog、New Relic、Grafana Cloud 或自托管的 Prometheus 实例。

  如果你想迁移到 New Relic,需要使用 Prometheus Docker 映像,并关闭自托管监控堆栈。

  

  New Relic 仪表盘示例汇总了最重要的统计数据。

  

  使用 New Relic 探测器监测世界各地运行时间。

  从自托管的 Grafana/Loki/Prometheus 堆栈迁移到 New Relic 简化了操作界面。更重要的是,即使 AWS 区域关闭,使用者仍然会收到警报。

  至于如何从 Django app 中公开指标,作者利用 django prometheus 库,只需在应用程序中注册一个新的计数器 / 仪表:

  

  这一指标和其他指标将在服务器的 / metrics 端点中公开。Prometheus 每分钟都会自动抓取这个端点,将指标发送至 New Relic。

  

  由于 Prometheus 整合,这个指标会自动出现在 New Relic 中。

  错误跟踪

  每个人都认为自己的应用程序没有错误,直到进行错误跟踪时才发现错误。异常很容易在日志中丢失,更糟的是,你知道异常的存在,但由于缺少上下文而无法复现问题。

  作者采用 Sentry 来聚合应用程序中的错误。检测 Django app 非常简单,如下所示

  

  Sentry 非常有帮助,因为它自动收集了一堆关于异常发生时出现何种异常的上下文信息:

  

  异常发生时,Sentry 会聚集异常并通知使用者。

  作者使用 Slack #alerts 通道来集中所有的警告,包括停机、cron job 失败、安全警告、性能退化、应用程序异常等。这样做的好处是当多个服务同时进行 ping 操作时,可以将问题关联起来,并处理看似不相关的问题。

  

  澳大利亚悉尼 CDN 端点下降导致的 Slack 警告。

  在进行深入研究时,作者还使用 cProfile 和 snakeviz 之类的工具来更好地了解分配、调用次数以及有关 app 性能的其他统计信息。

  

  cProfile 和 snakeviz 是可用于分析本地 Python 代码的工具。

  作者还使用本地计算机上的 Django debug toolbar 来方便地检查视图触发的查询,预览开发期间发送的电子邮件。

  

  Django 的 Debug 工具栏非常适合在本地开发中检查内容、以及预览事务性邮件。

  原文链接:https://anthonynsimon.com/blog/one-man-saas-architecture/

  CVPR 2021 线下论文分享会

  为更好的服务 AI 社区,促进国内计算机视觉学术交流,机器之心计划于 6 月 12 日组织大型「CVPR 2021 线下论文分享会」。

  本次活动将设置Keynote、 论文分享和 Poster 环节,邀请顶级专家、论文作者与现场参会观众共同交流。欢迎论文作者、AI 社区从业者们积极报名参与。

  点击阅读原文 ,了解详情并参与报名。

  

  © THE END

  转载请联系本公众号获得授权

  投稿或寻求报道:content@jiqizhixin.com

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐

突发!中国起诉澳大利亚!

中国基金报
2021-06-24 17:14:43

康复后才是噩梦的开始,半数新冠轻症患者康复半年后出现各种症状

生物世界
2021-06-24 13:00:44

中央安排部署后,13位省级党委书记前往家中拜访了他们

政知新媒体
2021-06-24 19:12:08

首位公开患艾滋病的女星:19岁封国际女神,21岁嫁入豪门…媲美林青霞,她是一代传奇!

VIKAN薇
2021-06-23 13:30:36

银行账户莫名多出10亿,佛州奶奶一夜暴富!不过后来这展开…??!

英国那些事儿
2021-06-24 03:28:17

夜场大姐爱上小鲜肉:要不是老娘甩了200万给你,你会跟我结婚?

野离离
2021-06-24 07:00:02

回归理性的618 ,是什么激起了年轻人的多巴胺?

智谷趋势
2021-06-24 11:05:36

这个曾叫板中国的菲律宾前总统,今天去世了!

牛弹琴
2021-06-24 12:09:27

38岁郭敬明近照认不出,举铁过猛,脖子和脸一样粗,身材比例奇怪

谈资
2021-06-23 12:41:17

女子给父亲邮寄两条高档香烟 收货后发现烟上的做的记号不见了

慢镜头看社会
2021-06-24 01:14:47

不允许中国参与?美国警告各国不准合作,重大项目被迫喊停

第一眼界
2021-06-24 10:09:17

一边收废品一边画油画,绍兴有位“陋室画家”,突然爆红的他每天照样出门收废品

钱江晚报
2021-06-23 09:10:37

65:41,中国完胜!彻查美国和加拿大,让西方国家这次很没面子?

王晓莹
2021-06-24 13:27:56

英国男子家中树因越界被邻居锯掉一半 当地居民赶来拍照

海外网
2021-06-24 14:54:06

冷战后第一次,俄罗斯实弹驱逐北约军舰!

牛弹琴
2021-06-24 07:41:00

别瞎吹了,他自己都不知道什么叫演技

影探
2021-06-23 19:07:40

45万一平!落马官员深圳豪宅拍卖,228㎡成交价6317万!还要交3000多万的税!网友震惊了

中国基金报
2021-06-24 11:03:17

发射基地传来噩耗!“一箭五飞”有去无回,60颗卫星升空失败

环球新军事
2021-06-24 14:20:49

突发!90吨重打桩机倒塌,甬港现代集团董事长身亡!震惊地产圈!

财经正解局
2021-06-23 16:59:31

新婚2个月妻子查出癌症,丈夫求离婚,妻子:你有没有道德底线

清白路人
2021-06-23 23:01:24
2021-06-24 20:49:08
机器之心Pro
机器之心Pro
专业的人工智能媒体
6078文章数 125586关注度
往期回顾 全部

科技要闻

"卫星互联网基建,我们想做华为"

头条要闻

快手宣布取消"大小周"加班 股价腰斩 字节跳动却吵翻

头条要闻

深圳228㎡豪宅成交价6317万 原业主系三亚落马书记

体育要闻

他把老鹰当小鸡,反让雄鹿被啄食

娱乐要闻

刘诗诗扎低马尾穿黑西装 气质脱俗

财经要闻

汽车要闻

预售29.99万-39.99万 一汽-大众揽境今晚上市

态度原创

本地
时尚
旅游
艺术
军事航空

本地新闻

福建老鼠干,在阴间美食界到底是什么水平?

1098克拉!世界第三大钻石在非洲南部被挖出

旅游要闻

仲夏伊犁 藏着中国最美的色彩

艺术要闻

当绘画不再关注精神,艺术就失去了永恒的生命力

军事要闻

央视报道解放军双人战斗小组演练巷战攻坚