超适合小项目的 K8S 部署策略

简介: Kubernetes 的稳健性、可靠性使它成为现阶段最流行的云原生技术之一,但也有不少用户反映, Kubernetes 技术学习起来十分复杂,只适用于大集群且成本较高。这篇文章将打破你的观念,教你在小型项目中部署 Kubernetes 集群。

Kubernetes 的稳健性、可靠性使它成为现阶段最流行的云 原生技术之一,但也有不少用户反映, Kubernetes 技术学习起来十分复杂,只适用于大集群且成本较高。这篇文章将打破你的观念,教你在小型项目中部署 Kubernetes 集群。


选择 K8S 部署小型集群的三大理由


理由一:花费时间少

在部署小型集群之前,你需要思考以下这些问题:


  • 应该如何部署应用程序?(仅仅 rsync 到服务器?)

  • 依赖关系是怎么样的?(如果利用 python 或 ruby,你必须在服务器上安装它们!)

  • 手动运行命令?(如果以 nohup 的方式在后台运行二进制文件这可能不是最好的选择,但去配置路由服务,是否还需要学习 systemd?)

  • 如何通过不同域名或 HTTP 路径运行多个应用程序?(你可能需要设置 haproxy 或 Nginx!)

  • 当更新应用程序后应该如何推出新变化?(停止服务、部署代码、重启服务?如何避免停机?)

  • 如果搞砸了部署怎么办?有什么方法可以回滚?

  • 应用程序是否需要使用其他服务?又该如何配置这些服务?(如:redis)


以上这些问题很有可能在你部署小型集群时出现,但 Kubernetes 为上述所有问题都提供了解决方案。或许还有其他方法可以解决上述问题,但是利用 Kubernetes 往往事半功倍,因为我们需要更多的时间专注于应用程序。


理由二:Kubernetes 记录整个部署过程

让我们看看利用 Kubernetes 部署集群的第二个理由。


你在工作时是否也是这样的状态:我上次运行了什么命令?当时服务器在运行什么服务?这让我想到了著名的 bash.org:


<erno> hm. I've lost a machine.. literally _lost_. it responds to ping, it works completely, I just can't figure out where in my apartment it is.

http://bash.org/?5273


这种情况曾经出现在我的工作中,让原本 10 分钟的工作量变成了一个周末。


但是如果你选择 Kubernetes 部署集群,就不会有这种困扰。因为 Kubernetes 使用描述性格式,如此用户就可以很轻松地知道接下来应该运行哪些内容,如何部署构建块。此外,控制层也会正常处理节点故障并自动重新调度 Pod。(对于像 Web 应用程序这样的无状态服务,就不再需要担心失败。)


理由三:Kubernetes 简单易学

Kubernetes 拥有自己的词汇表、工具,以及与传统 Unix 完全不同的配置服务器。Kubernetes 的知识足以建立和维护基础设施。使用 Kubernetes,你可以完全可以在 Kubernetes 中配置服务,无需 SSH 到服务器。你不必学习 systemd 也不必知道什么是运行级别; 你不必格式化磁盘,或学习如何使用 ps,vim。


我通过一个例子,来证明我的观点!


这是利用 Unix :

[Unit]
Description=The NGINX HTTP and reverse proxy server
After=syslog.target network.target remote-fs.target nss-lookup.target[Service]
Type=forking
PIDFile=/run/nginx.pid
ExecStartPre=/usr/sbin/nginx -t
ExecStart=/usr/sbin/nginx
ExecReload=/usr/sbin/nginx -s reload
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true
[Install]
WantedBy=multi-user.target

真的比利用 Kubernetes 难:

apiVersion: apps/v1
kind: Deployment
metadata:
 name: my-nginx
spec:
 selector:
 matchLabels:
 run: my-nginx
 replicas: 1
 template:
 metadata:
 labels:
 run: my-nginx
 spec:
 containers:
 - name: my-nginx
 image: nginx
 ports:
 - containerPort: 80

当你远程执行基础架构管理时,是不需要手动维护服务器的。你可以使用:ansible、salt、chef、puppet 等来完成这件事。当然,你需要学习使用很多 Kubernetes 相关工具,这要比学习替代品轻松的多。


小 结

Kubernetes 并不是将一件事做到极致的工具而是一个全方位的解决方案,它取代了开发人员习惯使用的许多技术和工具。


接下来我们用实际操作,为大家部署一个小型 Kubernetes 集群。


建立小型 Kubernetes 集群


下面就开始我们的教程。对于这个例子,我们将使用谷歌的 Kubernetes引擎(GKE),但如果谷歌不是你的菜,你也可以选择亚马逊(EKS)或微软(AKS)。


要构建我们的 Kubernetes 集群,我们将需要:


  • 域名(10 美元 /年,具体取决于域名);

  • DNS 主机由 cloudflare 提供(免费);

  • GKE 中的 3 个 node kubernetes 集群(5 美元 / 月);

  • 将 Webapp 作为 Docker 容器发送到 Google Container Registry(GCR)(免费);

  • 一些 yaml 文件配置 Kubernetes。


此外,为了节省成本,我们不会使用谷歌的 ingress controller 。相反,我们将在每个节点上运行 Nginx 作为 Daemon,并构建一个自定义运算符,将工作节点外部 IP 地址与 Cloudflare 同步。


谷歌设置

首先访问 console.cloud.google.com 并创建一个项目(如果你还没有项目)。你还需要设置结算帐户。然后前往 hamburger 菜单中的 Kubernetes 页面并创建一个新的集群。


你需要执行以下操作:

  • 选择 Zonal 区域类型(我使用了 us-central1-a 作为我的区域);

  • 选择你的 Kubernetes 版本;

  • 使用最便宜的实例类型(f1-micro)创建 3 个 node 池;

  • 对于该节点池,在高级屏幕中,将引导磁盘大小设置为 10GB,启用可抢占的 node(它们更便宜),启用自动升级和自动修复;

  • 在节点池下面还有一些其他选项。我们想要禁用 HTTP 负载均衡(GCP 中的负载均衡很昂贵且不稳定)并且还禁用所有 StackDriver 的服务以及禁用 Kubernetes dashboard 。


通过设置所有这些选项,你可以继续创建集群。

以下是减少的成本:

  • Kubernetes 控制层:免费,因为谷歌不收取专家的费用;

  • Kubernetes 工作节点:5.04 美元/月,3 个微节点通常为 11.65 美元/月,通过使用它们的可抢占性,我们将其降至 7.67 美元/月(“永久免费”等级则达到 5.04 美元);

  • 存储成本:免费,存储成本可以在 GCP 中累计。我们将免费获得 30GB 的永久磁盘,这就是我们选择 10GB 大小的原因;

  • 负载均衡器成本:免费,我们禁用 HTTP 负载均衡,因为仅此一项费用将达到 18 美元/月。相反,我们将在每个节点上运行我们自己的 HTTP 代理,并将 DNS 指向公共 IP;

  • 网络费用:免费,只要你每月低于 1GB,出口就是免费的(之后每GB 8 美分)。


因此,我们可以拥有一个 3 个节点的 Kubernetes 集群,价格与单个数字机器相同。


除了设置 GKE 之外,我们还需要添加一些防火墙规则,以允许外网点击我们节点上的 HTTP 端口。操作是:从 hamburger 菜单转到 VPC 网络,防火墙规则添加为 TCP 端口 80 和 443 的规则,IP 范围为 0.0.0.0/0。


1
本地设置

随着集群的启动和运行,我们就可以对其进行配置。通过 cloud.google.com/sdk/docs 的说明安装 gcloud 工具。


安装完成后,你可以通过运行以下命令进行设置:

gcloud auth login

你还需安装 Docker,将其连接到 GCR 上,方便你进行容器推送:

gcloud auth configure-docker

你也可以按照此处的说明安装和设置 kubectl (此工具适用于 Windows,OSX 或 Linux)。

 

gcloud components install kubectl gcloud config set project PROJECT_ID gcloud config set compute/zone COMPUTE_ZONE gcloud container clusters get-credentials CLUSTER_NAME

构建 Web 应用程序

你可以使用任何编程语言构建 Web 应用。我们只需构建一个 port 端口的 HTTP 应用程序。就个人而言,我更喜欢在 Go 中构建这些应用程序,但对于某些类型,让我们尝试使用 Crystal。


创建一个 main.cr 文件:

# crystal-www-example/main.crrequire "http/server"Signal::INT.trap do
 exit
end

server = HTTP::Server.new do |context|
 context.response.content_type = "text/plain"
 context.response.print "Hello world from crystal-www-example! The time is #{Time.now}"end

server.bind_tcp("0.0.0.0", 8080)
puts "Listening on http://0.0.0.0:8080"server.listen

我们还需要一个 Dockerfile:

# crystal-www-example/Dockerfile
FROM crystallang/crystal:0.26.1 as builder

COPY main.cr main.cr

RUN crystal build -o /bin/crystal-www-example main.cr --release

ENTRYPOINT [ "/bin/crystal-www-example" ]

我们可以通过以下命令来构建和测试我们的 Web 应用程序:

 

docker build -t gcr.io/PROJECT_ID/crystal-www-example:latest . docker run -p 8080:8080 gcr.io/PROJECT_ID/crystal-www-example:latest

然后输入 localhost:8080 在浏览器中访问。接着我们可以通过以下方式将我们的应用程序推到 GCR 中运行:

 

docker push gcr.io/PROJECT_ID/crystal-www-example:latest

配置 Kubernetes

对于此示例,我们将创建几个 yaml 文件来表示各种服务,然后通过运行 kubectl apply 在集群中配置它们。Kubernetes 的配置具有描述性,这些 yaml 文件将会告诉 Kubernetes 我们希望看到的状态。


我们需要做的事情:

  • 为我们的 crystal-www-example Web 应用程序创建部署和服务;

  • 为 Nginx 创建一个 Daemon Set 和 Config Map;

  • 运行自定义应用程序使用 Cloudflare 到 DNS 同步 node IP。


Web App 配置

首先让我们配置 webapp:(先将 PROJECT_ID 替换为你的项目 ID)

# kubernetes-config/crystal-www-example.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
 name: crystal-www-example
 labels:
 app: crystal-www-example
spec:
 replicas: 1
 selector:
 matchLabels:
 app: crystal-www-example
 template:
 metadata:
 labels:
 app: crystal-www-example
 spec:
 containers:
 - name: crystal-www-example
 image: gcr.io/PROJECT_ID/crystal-www-example:latest
 ports:
 - containerPort: 8080---

kind: Service
apiVersion: v1
metadata:
 name: crystal-www-example
spec:
 selector:
 app: crystal-www-example
 ports:
 - protocol: TCP
 port: 8080
 targetPort: 8080

现在创建一个 Deployment,它会通知 Kubernetes 创建一个 Pod,其中包含一个运行 Docker 容器的容器,以及一个用于集群内的 service discovery 。要应用此配置运行(在 kubernetes-config 文件夹中):

kubectl apply -f .

我们可以使用以下方法测试它是否在运行:

kubectl get pod
# you should see something like:
# crystal-www-example-698bbb44c5-l9hj9 1/1 Running 0 5m

我们还可以创建代理 API,以便我们访问它:

kubectl proxy

然后访问:

http://localhost:8001/api/v1/namespaces/default/services/crystal-www-example/proxy/


Nginx 配置

通常,在 Kubernetes 中处理 HTTP 服务时,你会使用 ingress controller。不幸的是,Google 的 HTTP 负载均衡器非常昂贵,因此我们将运行自己的 HTTP 代理并手动配置它。


我们将使用 Daemon Set 和 Config Map。Daemon Set 是在每个节点上运行的应用程序。Config Map 基本上是一个小文件,我们可以在容器中安装它,我们将存储 Nginx 配置。


yaml 看起来像这样:

apiVersion: apps/v1
kind: DaemonSet
metadata:
 name: nginx
 labels:
 app: nginx
spec:
 selector:
 matchLabels:
 app: nginx
 template:
 metadata:
 labels:
 app: nginx
 spec:
 hostNetwork: true
 dnsPolicy: ClusterFirstWithHostNet
 containers:
 - image: nginx:1.15.3-alpine
 name: nginx
 ports:
 - name: http
 containerPort: 80
 hostPort: 80
 volumeMounts:
 - name: "config"
 mountPath: "/etc/nginx"
 volumes:
 - name: config
 configMap:
 name: nginx-conf

---

apiVersion: v1
kind: ConfigMap
metadata:
 name: nginx-conf
data:
 nginx.conf: |
 worker_processes 1;
 error_log /dev/stdout info;

 events {
 worker_connections 10;
 }

 http {
 access_log /dev/stdout;

 server {
 listen 80;
 location / {
 proxy_pass http://crystal-www-example.default.svc.cluster.local:8080;
 }
 }
 }

你可以看到我们如何在 Nginx 容器内挂载 config map 的 nginx.conf。我们还在规范上设置了两个附加字段:hostNetwork: true、dnsPolicy: ClusterFirstWithHostNet 。

  • hostNetwork: true 以便我们可以绑定主机端口并从外网到达 Nginx;

  • dnsPolicy: ClusterFirstWithHostNet 以便我们可以访问集群内的服务。


应用更改:通过点击节点的公共 IP 来到达 Nginx。


你可以通过运行找到:

kubectl get node -o yaml
# look for:
# - address: ...
# type: ExternalIP

我们的网络应用程序现在可通过互联网访问了。现在想想给它起一个好听的名字!


连接 DNS

我们需要 A 为集群的节点设置 3 条 DNS 记录:

1

然后添加一个 CNAME 条目以指向那些 A 记录。(即 www.example.com CNAME kubernetes.example.com)我们可以手动执行此操作,但最好自动执行此操作,以便在扩展或替换节点时 DNS 记录自动更新。


我认为这也是一个很好的说明示例,说明如何让 Kubernetes 为你工作而不是反对它。Kubernetes 完全可编写脚本,并且具有强大的 API。因此你可以使用不太难编写的自定义组件填补空白。我为此构建了一个小型 Go 应用程序,可在此处找到:kubernetes-cloudflare-sync。


建立一个 informer:

factory := informers.NewSharedInformerFactory(client, time.Minute)
lister := factory.Core().V1().Nodes().Lister()
informer := factory.Core().V1().Nodes().Informer()
informer.AddEventHandler(cache.ResourceEventHandlerFuncs{
 AddFunc: func(obj interface{}) {
 resync()
 },
 UpdateFunc: func(oldObj, newObj interface{}) {
 resync()
 },
 DeleteFunc: func(obj interface{}) {
 resync()
 },
})
informer.Run(stop)

informer 将在节点更改时随时调用我的 resync 函数。然后使用 Cloudflare API 库(github.com/cloudflare/cloudflare-go)同步 IP ,类似于:

var ips []stringfor _, node := range nodes { for _, addr := range node.Status.Addresses { if addr.Type == core_v1.NodeExternalIP {
 ips = append(ips, addr.Address)
 }
 }
}
sort.Strings(ips)for _, ip := range ips {
 api.CreateDNSRecord(zoneID, cloudflare.DNSRecord{
 Type: "A",
 Name: options.DNSName,
 Content: ip,
 TTL: 120,
 Proxied: false,
 })
}

就像我们的网络应用程序一样,我们将此应用程序作为 Kubernetes 中的部署:

apiVersion: apps/v1
kind: Deployment
metadata:
 name: kubernetes-cloudflare-sync
 labels:
 app: kubernetes-cloudflare-sync
spec:
 replicas: 1
 selector:
 matchLabels:
 app: kubernetes-cloudflare-sync
 template:
 metadata:
 labels:
 app: kubernetes-cloudflare-sync
 spec:
 serviceAccountName: kubernetes-cloudflare-sync
 containers:
 - name: kubernetes-cloudflare-sync
 image: gcr.io/PROJECT_ID/kubernetes-cloudflare-sync
 args:
 - --dns-name=kubernetes.example.com
 env:
 - name: CF_API_KEY
 valueFrom:
 secretKeyRef:
 name: cloudflare
 key: api-key
 - name: CF_API_EMAIL
 valueFrom:
 secretKeyRef:
 name: cloudflare
 key: email

你需要使用 cloudflare api 密钥和电子邮件地址创建 Kubernetes 密码:

kubectl create secret generic cloudflare --from-literal=email='EMAIL' --from-literal=api-key='API_KEY'

你还需要创建服务帐户(它允许我们的部署访问 Kubernetes API 来检索节点)。首次运行(特别是对于 GKE):

kubectl create clusterrolebinding cluster-admin-binding --clusterrole cluster-admin --user YOUR_EMAIL_ADDRESS_HERE

然后申请:

apiVersion: v1
kind: ServiceAccount
metadata:
 name: kubernetes-cloudflare-sync
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
 name: kubernetes-cloudflare-sync
rules:
- apiGroups: [""]
 resources: ["nodes"]
 verbs: ["list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
 name: kubernetes-cloudflare-sync-viewer
roleRef:
 apiGroup: rbac.authorization.k8s.io
 kind: ClusterRole
 name: kubernetes-cloudflare-sync
subjects:
- kind: ServiceAccount
 name: kubernetes-cloudflare-sync
 namespace: default

配置就绪后,运行 Cloudflare 的应用程序将在任何节点更改时被更新。以上就是基于 Kubernetes 部署小型集群的详细教程。

总 结

Kubernetes 就是这样一个收放自如的技术。就像你可能永远用不到 SQL 数据库中的所有功能,但你不得不承认 SQL 数据库极大地提高了你快速交付解决方案的能力。

Kubernetes 与 SQL 十分相似。在 Kubernetes 庞大的技术体系下,我们也并不能用到所有功能,却能在每个项目中恰到好处的使用部分功能实现完美部署。在每次利用 Kubernetes 部署小型集群时,我都会从中获得新的认知。

所以我的观点是,Kubernetes 对于小型部署也很有意义,而且既易于使用又便宜。如果你从来没有尝试过,现在就开动起来吧!

本文转自掘金-超适合小项目的 K8S 部署策略

相关实践学习
容器服务Serverless版ACK Serverless 快速入门:在线魔方应用部署和监控
通过本实验,您将了解到容器服务Serverless版ACK Serverless 的基本产品能力,即可以实现快速部署一个在线魔方应用,并借助阿里云容器服务成熟的产品生态,实现在线应用的企业级监控,提升应用稳定性。
云原生实践公开课
课程大纲 开篇:如何学习并实践云原生技术 基础篇: 5 步上手 Kubernetes 进阶篇:生产环境下的 K8s 实践 相关的阿里云产品:容器服务&nbsp;ACK 容器服务&nbsp;Kubernetes&nbsp;版(简称&nbsp;ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情:&nbsp;https://www.aliyun.com/product/kubernetes
相关文章
|
3天前
|
存储 运维 Kubernetes
Kubernetes 集群的监控与维护策略
【4月更文挑战第23天】 在微服务架构日益盛行的当下,容器编排工具如 Kubernetes 成为了运维工作的重要环节。然而,随着集群规模的增长和复杂性的提升,如何确保 Kubernetes 集群的高效稳定运行成为了一大挑战。本文将深入探讨 Kubernetes 集群的监控要点、常见问题及解决方案,并提出一系列切实可行的维护策略,旨在帮助运维人员有效管理和维护 Kubernetes 环境,保障服务的持续可用性和性能优化。
|
28天前
|
Kubernetes 网络协议 应用服务中间件
K8S二进制部署实践-1.15.5
K8S二进制部署实践-1.15.5
34 0
|
2月前
|
运维
计算巢如何使用fluxcd在ack部署helm chart
为支持helm服务运维管理功能,现在改用fluxcd的方式进行helm chart部署,这里计算巢对fluxcd进行部署helm chart的过程进行了封装,封装成了ROS公共模块MODULE::ACS::ComputeNest::FluxOciHelmDeploy,下面将主要介绍下怎么使用这个模块在计算巢中进行Helm Chart的部署。
36 3
|
2月前
|
Kubernetes 容器
使用sealer部署k8s记录
使用sealer部署k8s记录
|
2月前
|
存储 Kubernetes 容器
百度搜索:蓝易云【Kubernetes使用helm部署NFS Provisioner】
现在,你已经成功使用Helm部署了NFS Provisioner,并且可以在Kubernetes中创建使用NFS存储的PersistentVolumeClaim。
44 10
|
2月前
|
Kubernetes 应用服务中间件 nginx
百度搜索:蓝易云【使用Kubernetes部署Nginx应用教程】
现在,你已经成功在Kubernetes集群上部署了Nginx应用。通过访问Service的外部IP地址,你可以访问Nginx服务。
42 4
|
2月前
|
存储 Kubernetes 网络协议
使用 K8S 部署 RSS 全套自托管解决方案 - RssHub + Tiny Tiny Rss
使用 K8S 部署 RSS 全套自托管解决方案 - RssHub + Tiny Tiny Rss
|
30天前
|
Kubernetes 流计算 Perl
在Rancher K8s上部署Flink时,TaskManager连接不上并不断重启可能是由多种原因导致的
在Rancher K8s上部署Flink时,TaskManager连接不上并不断重启可能是由多种原因导致的
34 7
|
3月前
|
存储 Kubernetes Apache
pulsar on k8s 部署验证
pulsar on k8s 部署验证
|
2天前
|
存储 运维 Kubernetes
构建高效自动化运维体系:Ansible与Kubernetes的协同策略
【4月更文挑战第25天】 在当今快速迭代的软件开发过程中,自动化运维已成为提升效率、保证一致性和降低人为错误的关键。本文将探讨如何利用Ansible作为配置管理工具,以及Kubernetes作为容器编排系统,共同构建一个高效、可靠的自动化运维体系。文章首先概述了自动化运维的基本概念及其重要性,随后详细分析了Ansible与Kubernetes在自动化流程中的作用与优势,并通过一系列实践案例,展示了两者如何协同工作以优化部署、扩缩容和灾难恢复等关键运维任务。最后,文中还讨论了在实际应用中可能遇到的挑战及相应的解决策略,为读者提供了一套完整的自动化运维解决方案参考。