Ansible for k8s-深蓝源码网


时间: 2020-09-03 00:08:26 人气: 2289 评论: 0

用 ansible 来创建 k8s,这类项目已经很多了,在 github 上面随意可以搜到很多,而这篇文章主要介绍的是如果用 ansible 来做日常的 k8s 运维和开发部署。

本文中的例子可以在 https://github.com/u2takey/ansible-k8s 找到

helm 和 kustomize 的问题

从我第一次使用 helm 就觉得这个东西的设计实在古怪:

  • 一个包(配置)管理工具依赖服务端(tiller)
  • 做的事情很简单,设计却过于复杂(看看 helm 有多少命令和参数就知道了)
  • template 可读性很差,表达能力却很弱(受制于go-template的表达能力)
  • 99% 的用户不会安装 tiller, 只是拿来做 template 渲染工具,但是就算作为一个简单的渲染工具,helm也不好用
  • 其他缺陷:参考

后来出现了 kustomize,kustomize的设计并不依赖服务端,而是想做好本地渲染,然而几次使用之后发现,kustomize 显然还是失败了

  • kustomize 的设计有点像 ansible了,然而表达能力还是很差,设计却过于复杂
  • 作为了一个 yaml 工具,kustomize 带了太多k8s属性,比如 kustomize 了解什么是 images,什么是 configmap,这个设计显然不够灵活
  • 如果 kustomize (很有希望的)像ansible好好学习,能做好一个专用领域的 ansible 工具,易用性能肯定能好很多

求助于 ansible

关于运维和部署,ansible已经积累了太多经验,虽然本质上 ansible 最初的设计还是针对 "hosts", 并不是针对集群,ansible的 k8s module 质量也参差不齐,但是尽管如此,使用时候你会发现,ansible 在运维 k8s 的能力上还是很强。

用 ansible 部署 k8s 集群

这部分不是本文的重点,ansible 部署 k8s 是比较常见的 k8s 部署方式,这里给几个 star 比较高的项目,不再细述。

用 ansible 运维 k8s 服务

ansible 主要可以使用 k8s 模块来管理 k8s 资源

比如创建一个 namespace,可以使用下面的写法

- name: Create a k8s namespace
  k8s:
    name: testing
    api_version: v1
    kind: Namespace
    state: present

创建 service 的写法

- name: Create a Service object from an inline definition
  k8s:
    state: present
    definition:
      apiVersion: v1
      kind: Service
      metadata:
        name: web
        namespace: testing
        labels:
          app: galaxy
          service: web
      spec:
        selector:
          app: galaxy
          service: web
        ports:
        - protocol: TCP
          targetPort: 8000
          name: port-8000-tcp
          port: 8000

上面的这种 inline 的写法实际上可读性比较差,更推荐使用 src(读取文件) 或者 definition + lookup + template 语句的办法来创建资源,ansible 的 template 使用 jinja2 来渲染,表达能力很强。

- name: Create a Deployment by reading the definition from a local file
  k8s:
    state: present
    src: /testing/deployment.yml

- name: Read definition file from the Ansible controller file system after Jinja templating
  k8s:
    state: present
    definition: "{{ lookup('template', '/testing/deployment.yml.j2') }}"

一个完整的例子

下面我们看一个完整的例子,这个例子里面我们有两个集群,分别叫 4lr4c3wx8keawqnz, 并且我们在本地的 admin.conf 里面加入了这两个 context, 所以我们不用在 ansible config里面添加相关密钥信息。

  • 使用 ansible-galaxy 初始化 role
➜ ansible-galaxy role init nginx

➜ ll nginx
.rw-r--r-- 1.3k leiwang  4 Jan 15:11 README.md
drwxr-xr-x    - leiwang  4 Jan 15:11 defaults
drwxr-xr-x    - leiwang  4 Jan 15:11 files
drwxr-xr-x    - leiwang  4 Jan 15:11 handlers
drwxr-xr-x    - leiwang  4 Jan 15:11 meta
drwxr-xr-x    - leiwang  4 Jan 15:11 tasks
drwxr-xr-x    - leiwang  4 Jan 15:13 templates
drwxr-xr-x    - leiwang  4 Jan 15:11 tests
drwxr-xr-x    - leiwang  4 Jan 15:11 vars
  • 修改 host 和 ansible.cfg, 指向两个集群.
# ansible.cfg
[defaults]
inventory = hosts.ini
host_key_checking = False

pipelining = True
gathering = smart
fact_caching = jsonfile
fact_caching_timeout = 86400
fact_caching_connection = /tmp/ansible_fact_cache
forks = 20

# host
[test]
4lr4c3wx context=4lr4c3wx 
8keawqnz context=8keawqnz 

[test:vars]
ansible_connection=local 
ansible_python_interpreter=~/miniconda3/bin/python
  • 修改 task/main.yml, 这里我们编写两个任务,一是操作 namespace, 二是创建 nginx deployment 和 service,支持 namespace 和 state 参数,支持 state也就是说 支持创建或者删除,对 namespace的操作加上 ignore_errors, 因为创建或者删除 namespace 时可能会报错,我们希望忽略这种错误。
---
- debug: var=context
- name: set namespace {{ namespace }} to {{ state }}
  k8s:
    context: "{{ context }}"
    api_version: v1
    kind: Namespace
    name: "{{ namespace }}"
    state: "{{ state }}"
  ignore_errors: true
- name: set nginx deployment to {{ state }}
  k8s:
    context: "{{ context }}"
    state: "{{ state }}"
    definition: "{{ lookup('template', 'nginx.yml.j2') | from_yaml_all | list  }}"
    namespace: "{{ namespace }}"
  • nginx.yml.j2 里nginx deployment和service,实际上这两个 object 分开会更好,这里放在一起只是为了演示,如果放在一起应该用 from_yaml_all + list filter来处理
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: nginx
  namespace: {{ namespace }}
  labels:
    version: v2
spec:
 # 略
---
apiVersion: v1
kind: Service
metadata:
  name: nginx
  namespace: {{ namespace }}
spec:
  # 略
  • playbook include 刚刚编写的 nginx role
---
- name: example k8s playbook
  hosts: test
  vars:
    namespace: default
  roles:
  - nginx
  • 运行 playbook
➜ ansible-playbook main.yml

PLAY [example k8s playbook] *********************************************************************************************************************************************************

TASK [Gathering Facts] **************************************************************************************************************************************************************
ok: [test_cluster_2]
ok: [test_cluster_1]

TASK [nginx : debug] ****************************************************************************************************************************************************************
ok: [test_cluster_1] => {
    "context": "4lr4c3wx"
}
ok: [test_cluster_2] => {
    "context": "8keawqnz"
}

TASK [nginx : set namespace default to present] *************************************************************************************************************************************
ok: [test_cluster_1]
ok: [test_cluster_2]

TASK [nginx : set nginx deployment to present] **************************************************************************************************************************************
changed: [test_cluster_1]
changed: [test_cluster_2]

PLAY RECAP ******************************
						 技术沙龙 教程文章 热点综合					

评论