写点什么

如何用 Ansible 部署 Kubernetes 集群到 OpenStack

  • 2020-03-11
  • 本文字数:6121 字

    阅读完需:约 20 分钟

如何用Ansible部署Kubernetes集群到OpenStack

我们之前聊了把 OpenStack 跑在 K8S 上,如何基于 Kubernetes 在 TCP 云端创建私有云解决方法,运用在生产或在 OpenStack 启动虚拟化。今天换个姿势,我们来看看如何在 OpenStack 虚拟机上运行 Kubernetes 集群。


最近的 Austin OpenStack 峰会上,参会者中对容器感兴趣的人数之多,让我印象深刻。几乎所有跟容器相关的会议现在都意识到了它的优点。通过将应用程序容器化,就能够将主机操作系统虚拟化。这也就意味着,你可以在主机操作系统中为每个容器创建隔离环境,比如文件系统,网络堆栈和进程空间,令容器之间互相可见。此外,容器又是轻量级、轻便的,不仅仅跨操作系统,还可以跨云端。这些功能令开发者可以快速构建,部署,运输和扩容应用程序,而这些动作在虚拟机环境中是不可能实现的。


在峰会上,我有幸将自己参与的一个对我们团队有很大帮助的项目呈现给观众们看。可以点击这里查看我的presentation。


这个项目是为了在我们的 OpenStack Kilo 环境中建立起一个自动 Kubernetes 部署。在这篇博客帖中,我会描述我们的解决方法,并且在 Github 上面提供代码回购的总览。你可以利用其中一些代码来创建你自己的 Kubernetes 集群自动部署。记住,软件只在开发环境被测试,对于任何生产部署,都要确认你跟往常一样进行了必要的尽职调查。


首先要回答的问题就是 kubernetes 和 ansible 是什么,为什么要选择他们?


Kubernetes(K8S)是一个通过调用 API 来编排和管理 Docker 容器的平台。除了基本的编排功能,它还有持续驱动控制进程的功能,面向用户指定所需的状态。当使用这个平台的时候,你能将你的应用程序容器分组到一个叫 pod 的组合单元。pod 是一个分享网络和存储的容器组。当你创建 Docker 容器的时候,默认设置下,每个容器都会获得自己的网络命名空间也就是它自己的 TCP/IP 堆栈。Kubernetes 用-net=”|”设置到 Docker 里,以此将所有的 pod 容器的网络空间结合到一起。这个设置令容器可以再次使用另一个容器的网络堆栈。K8S 通过创建一个 pod 层面保持容器和它自己的网络堆栈来完成,所有的 pod 容器被配置来重新使用保持容器的网络空间。


在 pod 层面,Kubernetes 提供各种 services,比如调度,副本,自我修复,监控,命名/发现,身份识别,验证授权等等。Kubernetes 也有可以让开发者写自己模块的插件模版,然后在这个平台上面创建 services。就像这篇博客写得,Kubernetes 是最先进的、可编写和管理 Docker 容器的开源平台之一。


我们选择 Ansible 是因为它是当下最火、最直接、最容易使用的自动化平台之一。它运行代理较少,在基础架构上使用 ssh 来登录系统,执行你在 playbook 文件中描述的策略。这些策略被模式化为一个 yaml 格式的任务清单。在没有自动化的时候,这些就是必须由管理员来执行部署基础设施软件的手动任务。


这篇博客帖描述了在 OpenStack 虚拟机上面运行的 Kubernetes 集群。一个 K8S 集群有一个 master 节点,这个节点运行 API server 和一套运行在 pod 容器上的 worker 节点。设置使用的是 Ansible(>2.0),Ubuntu 和 Neutron 网络。测试后,使用 OpenStack kilo 来发布。Ansible 部署 K8S 软件组件,启动虚拟机,将虚拟机分类到 master 和 worker 节点,然后部署 Kubernetes 密钥清单。我们使用 neutron 来给 OpenStack 虚拟机和 K8S pod 容器提供网络连接。所有在测试环境中的虚拟机都运行 Ubuntu 14.04 服务器操作系统。


下图展示的是运行中的各种软件组件,以及他们是如何在集群中交互的。我会把这个图表作为资料来阐述自动进程,当你浏览这篇博客的时候,看到这个框图就会觉得说得通了。


设置

这个设置是假设你已经有一个 OpenStack 云运行核心 services,比如 Nova,Neutron,Glance 和 Keystone。你还需要>2.X 的 ansible 版本在一个有凭证和网络连通 ssh 到计算节点和虚拟机。这个 ansible 节点也需要能够访问 openStack API。我在我的 Macbook 上面用这些命令安装了 ansible:


sudo easy_install pipsudo pip install ansible
复制代码


在你安装了 ansible 之后,用命令行:“ansible-version”来验证它的版本。它应该输出一个 2.X 发布版本。

Kubernetes 集群 Deployment

自动化集群配置由三个 ansible playbooks 控制。你可以点击这里拉取 playbooks,模版和代码这三个 playbooks 是:


·      launch-instances.yml — launches kubernetescluster instances·      deploy-docker.yml  — deploys docker onall of the cluster instances·      deploy-kubernetes.yml — deploys kubernetescontrol and worker software components and brings up the cluster
复制代码


所有的 playbooks 从一个叫做 settings.yml 的文件中获取他们输入变量,这是根据设置文件参考的。设置文件中的节点代码字典和他们的原数据(也叫做标签)在集群指定节点的名字,标签在应用程序启动的时候被注入到节点里面。这些标签在运行 playbooks 的时候,被云库存脚本用来将节点分类为 master 和 worker。比如,标签为 ansible­_host_groups 的节点是 k8s_master 会被分类为 master 节点,而标签值等于 k8s_worker 会被分类为 workers。设置文件也包括名为 os_cloud_profile 的代码字典,它给 ansible 提供 nova 虚拟机启动设置。为了开启实例,如下运行 playbook:


ansible-playbook -i hosts launch-instances.yml.
复制代码


如果一切进行顺利,你会看到所有的 Nova 实例已经在 OpenStack 云上准确无误地创建好了。这些实例会提供底层基础设施来运行 K8S 集群。在增加实例之后,你可以运行剩下的 playbooks 来部署 Docker 和 Kubernetes。在 playbook 运行的时候,使用名为‘inventory.py’库存脚本来分类节点,这样 control 和 worker 组件就会被部署到正确的虚拟机上。


按如下所示运行 playbooks:


ansible-playbook -i scripts/inventory.py deploy-docker.ymlansible-playbook -i scripts/inventory.py deploy-kubernetes.yml
复制代码


K8S 集群的控制面板包括了 API 服务器,调度器,etcd 数据库和 kube controller manager 通过一个 master 密钥清单文件。这个文件名为 master-manifest.j2 可以在模版文件夹里面找到。K8S 控制面板软件的版本是由设置文件决的。这个名为 deploy-kubernetes.yml 的 playbook 是第一次下载和部署 kubelet 和 kube-proxy 二进制,并且在所有节点上开启这两个 services。然后 master-manifest 模版文件就会在 master 节点上被部署到一个叫做/etc/kubernetes/manifest 的 config 目录。这个目录被 kubelet daemon 进程监视,它开启了所有的提供控制面板 services 的 Docker 容器。当你使用 Docker ps 命令的时候,你会看到 kube-apiserver,kube-controller-manager,etcd 和 kube-schedules 进程在 master 节点里运行在他们自己的容器上。


API 服务器被配置来使用 HTTPS 服务 API。SSL 所需的证书是通过将 make-ca-cert.sh 脚本作为 playbook 任务之一来运行生成的。这个脚本在每个节点上的证书目录中生成了以下证书。这个在每个节点上都有生成,因为 Docker daemon 也使用相同的服务器证书来配置 TLS。cert 文件目录值在设置文件中也是可配置的。

ca.pem——自签 CA 证书

Server.crt/server.key——签署的 kube 服务器端证书和它的密钥文件。这个 cert 文件也可以被 Docker Daemon 进程用来确保客户端安全访问。


cert.pem/key.pem——签署的客户端证书和它的密钥文件。kubectl 和 docker 客户使用。


在客户机上面,你可以在 repo 里面找到这些 certs 文件夹。在客户机里用 convention.env 为每个节点都创建了 Docker 环境文件。你可以追踪这个环境变量的来源,然后运行 Docker 客户端而不是 Docker 主机。比如,为了在名为 master1 的 master 节点上运行 Docker 命令,第一步就是执行“source master1.env”,然后运行命令。同样,对于 kubectl 客户端来说,config 文件是由必要的凭证和集群 master IP 地址来创建的。Config 文件可以在 $HOME/.kube/config 中找。这样你可以在集群上的终端窗口运行 kubectl 命令。



在这篇博客帖中,我会描述如何使用 OpenStack neutron service 来连接 K8S pods。这跟 GCE 的设置有些相似。其实也可以选择其他的,比如 Flannel,使用 UDP 封装在现有租户 neutron 中为路由 pod 创建一个覆盖网络选项。使用 neutron 为 pod 网络删除这个为容器覆盖又覆盖的网络构架。


要重点注意的是在 K8S 中每个 pod(也就是一组容器)都有一个 IP 地址。这就区别于在 Docker 中的网络模版,在这里每个容器有主机的私有 IP 地址。为了让 K8S 网络运行起来,pod 的 IP 地址必须是不需要 NAT 的,可路由的。这也就意味着两件事情:


a)当一个 pod 容器与其它 pod 中的容器交流的时候,通信必须是直接路由,不需要 NAT 的。


b)当一个 pod 容器与虚拟机的 IP 地址交流的时候,通信必须是直接路由,不需要 NAT 的。


为了完成以上目的,第一步就是,在每个节点中名为 docker0 的默认 docker 桥被一个名为 cbr0 的 Linux 桥所替代。跨过所有节点,一个 IP 模块被分配给 pod 网络,比如说/16。这个模块被抽象化了,节点到 pod 的映射被创建在一个设置文件里。在以上图表中,我把 10.1.0.0/16 分配给 pod 网络,然后创建了以下映射:


node1 : 10.1.1.1/24node2: 10.1.2.1/24
nodeN: 10.1.n.1/24
复制代码


create-bridge.sh(create-bridge.sh)脚本创建 cbr0,然后使用在设置文件中定义好的映射来配置 pod 子网络的 IP 地址。


第二步就是配置租户路由器到路由流量,再到 pod 子网络。比如在以上的框图中,租户路由器肯定是被配置到路径中,再配置流量到 pod 子网络 10.1.1.0/24,配置到位于 private-subnet#1 上 node#1 的以太网络地址。同样的,路径必须添加在集群中指向每个节点的目的站来路由流量到 pod 网络。使用 add_neutron_routes.py 脚本完成这个步骤。


第三步就是添加 IP tables 规则到冒充流量,从 pod 子网络到为出站连接的网络。这是因为 neutron 租户路由器不知道它需要从 pod 子网络 SNAT 流量。


最后一步就是打开在每个节点的 Linux 内核上的 IP 转发,到路径包,再到网桥容器网络。这些任务都由 playbook deploy-kubernetes.yml 执行的。


运行这个 playbook 的最终结果就是,neutron 网络现在被编程来进行 pods 到网络间的路由通信。


注意:默认状态下,作为一个抗欺骗安全措施,neutron 在超管理器上安装 iptables 防火墙规则,来控制流量在虚拟机端口的来去。所以,当路由流量注入 pod 网络到虚拟机的端口,它是被超管理器防火墙过滤过的。所幸,有一个叫做 AllowedAddressPairs 的 neutron 扩展,它允许如 pod 子网络的 Havana 发布版本,来通过虚拟机监控程序防火墙。

暴露 Pod Services

出于实用性目的,每个 pod 必须放在服务抽象的前面。这个服务使用可以连接到 pod 容器里面运行的应用程序,来提供稳定的 IP 地址。这是因为 pod 能够在任意节点上被调度,而且可以从分配好的 node_pod_cidr 范围获取任意 IP 地址。同样的,当你扩展/缩减这些 pods 来容纳流量变化,或者当运行失败的 pods 通过平台再次创建,他们的 IP 地址就会改变。从客户角度来看,服务抽象要确保 pods 的 IP 地址保持固定。要重点注意的是,对于服务来说,CIDR,也就是 cluster_cidr,只在每个节点本地存活,并不需要被 neutron 租户路由器路由。这个服务 IP 流量被 K8S 用 proxy 功能(kube-proxy)分布到备份 pod,proxy 功能通常用 iptables 在每个节点中实施。


这个稳定的 service IP 可以用 Kubernetes 的 NodePort 性能暴露到外面。节点端口所做的事情就是,它使用 worker 节点的 IP 地址和一个高 TCP 端口 31000,来暴露服务 IP 地址和端口到外部。所以如果你分配一个浮动 IP 到节点,应用程序会在那个 IP 和它的节点 IP 提供流量。如果你使用一个 neutron 负载平衡器,那就添加 worker 节点成员,编写 vip 分布流量到节点端口。这个方法在以上框图中已经阐述。

服务发现

服务发现可以使用 DNS 集群 add-on 服务实现完全自动化。可以使用 skydns-manifest 和 skydns-service 来部署。K8S 会自动给每个在集群中定义的服务分配一个 DNS 名字。所以运行在 pod 里面的程序可以查找集群 DNS 服务器来解决服务名称和位置。集群 DNS 服务支持 A 和 SRV 记录查找。

结论

我希望这篇博客帖子阐明了如何用 Ansible 在 OpenStack 上创建 Kubernetes 集群。


本文转载自才云 Caicloud 公众号。


原文链接:https://mp.weixin.qq.com/s/LZefE8cRDiGlMmlGnxm2Cw


2020-03-11 19:541023

评论

发布
暂无评论
发现更多内容

安卓程序员必备hook技术之进阶篇

Java 程序员 后端

将项目转成MAVEN项目

Java 程序员 后端

常见的SQL面试题:经典50例

Java 程序员 后端

常见的社会潜规则有哪些?

Java 程序员 后端

干货第一弹-教你如何利用阿里开源工具进行排查线上CPU居高问题

Java 程序员 后端

应云而生,幽灵的威胁 - 云原生应用交付与运维的思考

Java 程序员 后端

官宣:恭喜 ChaosBlade 项目进入 CNCF Sandbox

Java 程序员 后端

官方都不推荐?为什么MySQL不推荐使用uuid作为主键?究竟有什么坏处

Java 程序员 后端

实时数据库 架构图

Java 程序员 后端

已开源!阿里巴巴SpringCloud微服务原理与架构项目实战,请签收

Java 程序员 后端

架构实战营 - 第三期 - 模块三作业

岚哲

极客时间 架构 架构实战营

年初入职 字节跳动 的Java面试经验分享(文档)

Java 程序员 后端

应届生想要找到一份Java开发的工作,需要达到什么水平?

Java 程序员 后端

模块三作业

小鹿

实战:第十一篇:StringRedisTemplate获取redis信息

Java 程序员 后端

带你了解代理模式

Java 程序员 后端

架构实战营 - 第三期 - 模块三作业

lucian

架构实战营

应用服务器集群的Session管理

Java 程序员 后端

宝藏图,引起的一堆问题,轻量级锁的不解(Synchronized锁的升级)

Java 程序员 后端

Kubernetes 给容器化部署和管理带来的好处

后台技术汇

Kubernetes 11月日更

实现一个百万级推送服务,除了它,还有谁

Java 程序员 后端

年前三面美团百度挂了,疫情间啃完阿里面试宝典,成功斩获offer

Java 程序员 后端

开发做了一两年了,感觉遇到了瓶颈,公司已经学不到太多东西,如何成长为技术大牛

Java 程序员 后端

.NET6新东西--Http Logging

喵叔

11月日更

Android C++系列:JNI 调用时缓存字段和方法 ID

轻口味

c++ android jni 11月日更

实战spring自定义属性(schema)

Java 程序员 后端

干掉GuavaCache:Caffeine才是本地缓存的王

Java 程序员 后端

工作三年的Java程序员应该达到什么水平?

Java 程序员 后端

将CSV的数据发送到kafka(java版)

Java 程序员 后端

完美!腾讯技术官发布Java零基础就业宝典,不用再怀疑人生了

Java 程序员 后端

幸亏有了这本623页的微服务框架实战笔记,一举拿下腾讯美团滴滴offer

Java 程序员 后端

如何用Ansible部署Kubernetes集群到OpenStack_行业深度_才云科技_InfoQ精选文章