用 Ansible 实现基于 OpenShift (Kubernetes) 的 DevOps

89 篇文章 3 订阅
15 篇文章 1 订阅

OpenShift 4.x HOL教程汇总

Ansible的Kubernetes模块

截止到目前,Ansible 2.9内置了以下模块用来对OpenShift和Kubernetes操作。

  • k8s – Manage Kubernetes (K8s) objects
  • k8s_auth – 登录认证模块
  • k8s_info – 描述Kubernetes的对象
  • k8s_scale – 扩展Deployment, ReplicaSet, ReplicationController或Job的数量
  • k8s_service – 管理Kubernetes的服务

Ansible访问OpenShift或Kubernetes的过程

Ansible是通过基于python的k8s模块(曾经是openshift_raw)访问OpenShift或Kubernetes服务器的。它采用REST的方式访问集群,因此不需要本地运行OpenShift或Kubernetes客户端。

不过如果运行Ansible的环境也有oc客户端,并且oc客户端已经登录集群了,那么Ansible模块可以共享这个登录会话连接,可以在Playbook中直接对Kubernetes进行操作即可。如果oc客户端未登录OpenShift集群,那么Ansible模块可直接登录OpenShift或Kubernetes,然后再能进行其它操作。
在这里插入图片描述

安装环境

编辑Ansible Playbook工具

为了编辑Ansible的Playbook文件,可以使用VSCode的Ansible插件,另外还可配合vscode-ssh插件远程编辑Playbook文件。Ansible插件可以提示模块和参数。
在这里插入图片描述

安装oc客户端

$ wget https://mirror.openshift.com/pub/openshift-v4/clients/ocp/4.5.5/openshift-client-linux-4.5.5.tar.gz 
$ tar -xzf openshift-client-linux-4.5.5.tar.gz -C /usr/bin/

安装Ansible

  1. 操作系统可以是RHEL 7/8、CentOS 7/8。用root用户依次执行以下命令安装rpm和ansible。
$ yum install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm
$ yum install ansible -y

说明:RHEL 7 使用“epel-release-latest-7.noarch.rpm”、RHEL 8 使用“epel-release-latest-8.noarch.rpm”。
2. 验证Ansible环境,其中Ansible的版本是2.9.11;“config file”是Ansible使用的配置文件;“configured module search path”是Ansible模块的目录;“ansible python module location”是python模块的目录;python使用的版本是3.6.8环境。

$ $ ansible --version
ansible 2.9.11
  config file = /home/student1/.ansible.cfg
  configured module search path = ['/home/student1/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python3.6/site-packages/ansible
  executable location = /usr/bin/ansible
  python version = 3.6.8 (default, Dec  5 2019, 15:45:45) [GCC 8.3.1 20191121 (Red Hat 8.3.1-5)]

安装python相关模块

根据Ansible的文档说明,为了能操作Kubernetes或OpenShift,需要安装以下python的模块。

$ pip install pyyaml 
$ pip install kubernetes
$ pip install openshift

通过Ansible实现DevOps

从github上获取YAML文件

  1. 创建内容如下的clone-git.yml文件,将本文用到的yaml文件从github上clone到本地的~/ansible目录。
- hosts: localhost
  gather_facts: no
  
  tasks:
  - name: Checkout The Code From Github Using Ansible.
    git:
      repo: 'https://github.com/liuxiaoyu-git/ansible-kubernetes.git'
      dest: ~/ansible
    register: clone
  1. 执行命令
$ ansible-playbook clone-git.yml
 
PLAY [localhost] ***********************************************************************************************************************************
 
TASK [Checkout The Code From Github Using Ansible.] ***********************************************************************************************************************************
changed: [localhost]
 
PLAY RECAP ***********************************************************************************************************************************
localhost                  : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
  1. 查看通过ansible下载的文件。
$ ll ~/ansible
total 24
-rw-rw-r--. 1 student1 student1 632 Aug 20 14:50 del-pod.yml
-rw-rw-r--. 1 student1 student1 465 Aug 20 14:50 hello-deployment.yml
-rw-rw-r--. 1 student1 student1 572 Aug 20 14:50 hello-openshift.yml
-rw-rw-r--. 1 student1 student1 415 Aug 20 14:50 pod-list.yml
-rw-rw-r--. 1 student1 student1 474 Aug 20 14:33 testing-login.yml
-rw-rw-r--. 1 student1 student1 178 Aug 20 14:33 testing-nologin.yml

创建NameSpace

  1. 查看testing-nologin.yml文件。本Playbook是在OpenShift中创建名为testing的项目。
    说明:在hosts中指定的是localhost,这是由于我们直接是在本机运行ansible-abp脚本,而不是在远程节点上运行ansible-abp脚本。
- hosts: localhost
  gather_facts: false

  tasks:
  - name: Create a k8s namespace
    k8s:
      name: testing
      api_version: v1
      kind: Namespace
      state: present
  1. oc客户端连到OpenShift集群。
$ oc login https://<OCP-API-Server>:6443 -u <USERNAME> -p <PASSWORD>
  1. 运行Ansible playbook,创建testing项目。可以看到Playbook运行结果是“changed=1”。
$ ansible-playbook testing-nologin.yml
 
PLAY [localhost] ***************************************************************************************************************************
 
TASK [Create a k8s namespace] **************************************************************************************************************
changed: [localhost]
 
PLAY RECAP *********************************************************************************************************************************
localhost                  : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
  1. 验证,查看testing项目。
$ oc get project testing
NAME      DISPLAY NAME   STATUS
testing                  Active
  1. 删除项目后退出客户端和集群的会话连接。
$ oc delete project testing
$ oc logout
  1. 再运行playbook,发现会出现错误。从错误提示看,是由于当前客户端没有连到OpenShift集群,所以对集群的操作报“ForbiddenError”。
$ ansible-playbook testing-nologin.yml
 
PLAY [localhost] ***********************************************************************************************************************************
 
TASK [Create a k8s namespace] ***********************************************************************************************************************************
An exception occurred during task execution. To see the full traceback, use -vvv. The error was:     raise ApiException(http_resp=r)
fatal: [localhost]: FAILED! => changed=false
  module_stderr: |-
    Traceback (most recent call last):
      File "/usr/local/lib/python3.6/site-packages/openshift/dynamic/discovery.py", line 72, in __init_cache
        self._cache = json.load(f, cls=CacheDecoder(self.client))
      File "/usr/lib64/python3.6/json/__init__.py", line 299, in load
        parse_constant=parse_constant, object_pairs_hook=object_pairs_hook, **kw)
      File "/usr/lib64/python3.6/json/__init__.py", line 367, in loads
        return cls(**kw).decode(s)
    TypeError: 'CacheDecoder' object is not callable
。。。。
。。。。
    openshift.dynamic.exceptions.ForbiddenError: 403
    Reason: Forbidden
    HTTP response headers: HTTPHeaderDict({'Cache-Control': 'no-cache, private', 'Content-Type': 'application/json', 'X-Content-Type-Options': 'nosniff', 'X-Kubernetes-Pf-Flowschema-Uid': '3404ba15-4ff8-485c-bf1b-a2e99429b516', 'X-Kubernetes-Pf-Prioritylevel-Uid': '37685748-0d25-4647-8911-4bc162270ee0', 'Date': 'Wed, 19 Aug 2020 15:24:30 GMT', 'Content-Length': '189'})
    HTTP response body: b'{"kind":"Status","apiVersion":"v1","metadata":{},"status":"Failure","message":"forbidden: User \\"system:anonymous\\" cannot get path \\"/apis\\"","reason":"Forbidden","details":{},"code":403}\n
  1. 刚刚oc客户端退出了和OpenShift集群的连接会话,这种情况下可以在playbook中先建立客户端和集群的连接会话,然后再进行操作。查看testing-login.yml文件,它使用了k8s_auth模块登录OpenShift集群,而host为集群的API-Server登录地址。另外为了简化,登录的usename和password直接用的是明文,建议在生产环境中使用加密方式提供登录密码。
- hosts: localhost
  gather_facts: false

  tasks:
  - name: Try to login to OCP cluster
    k8s_auth:
      host: https://api.cluster-shang-b982.shang-b982.example.opentlc.com:6443
      username: opentlc-mgr
      password: r3dh4t1!
      validate_certs: no
    register: k8s_auth_result

  - name: Create a k8s namespace
    k8s:
      name: testing
      api_version: v1
      kind: Namespace
      state: present
      api_key: "{{ k8s_auth_result.k8s_auth.api_key }}"
  1. 运行新的playbook,确认可以成功运行(changed=1)。
$ ansible-playbook testing-login.yml
 
PLAY [localhost] **********************************************************************************************************************************
 
TASK [Try to login to OCP cluster] **********************************************************************************************************************************
ok: [localhost]
 
TASK [Create a k8s namespace] **********************************************************************************************************************************
changed: [localhost]
 
PLAY RECAP **********************************************************************************************************************************
localhost                  : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
  1. 最后,再次用oc客户端登录OpenShift集群,并查看上一步创建的testing项目。

创建登录密码的加密文件

以上我们在testing-login.yml中直接使用了明文的登录密码。为了安全起见可以将密码加密,然后再在Playbook中使用。

  1. 执行命令创建加密密码的文件。该文件实际相当于一个对称秘钥,它有两个作用,1)用来对需要保护的进密码行加密,2)用来还原已经加密的密码。
$ echo 'mypassword' > decrypt_passwd
  1. 执行命令创建密码加密文件secrets,所有需要加密的密码放在此文件中。
$ ansible-vault create --vault-id=decrypt_passwd mysecrets

然后在编辑界面中将以下内容加入到文件中。后面在Playbook中 就可以用“ocp_password”访问到OpenShift使用的到密码“r3dh4t1!”。

ocp_password: r3dh4t1!
  1. 保存后可以查看mysecrets文件内容。
$ more mysecrets
$ANSIBLE_VAULT;1.1;AES256
30663865643634373038313139383537663138313463306534666231313136653139663632663863
3934353961666164326166653762323133386238343266320a666638653639366539303738663938
66386266373331366430363639666133393138633434373930646439303936373865663935663565
3263333033663065390a336332623131383364306337303734616132326130363038656335383366
65636133633038626139636538333437376535353139393562316535336133316338
  1. 可以用以下命令编辑内容被加密的mysecrets文件。
$ ansible-vault edit --vault-id=decrypt_passwd mysecrets

创建变量文件

以上我们在testing-login.yml中直接使用OpenShift的登录地址,这样如果该地址发生变化,我们不得不修改所有直接使用该地址的Playbook。为此,我们可以将这个地址存放在变量文件中,然后在后面的Playbook中统一引用“ocp_master”变量即可。

  1. 创建内容如下的myvars文件,其中包括了OpenShift的Master地址和登录OpenShift的用户。
ocp_master: https://api.cluster-shang-b982.shang-b982.example.opentlc.com:6443
ocp_username: opentlc-mgr

创建Deployment资源

  1. 查看hello-openshift.yml文件,它定义了一个Deployment的Kubernetes对象,其中部署了openshift/hello-openshift容器。
apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello-openshift
  labels:
    name: hello-openshift
spec:
  selector:
    matchLabels:
      app: hello-openshift
  replicas: 1
  template:
    metadata:
      labels:
        app: hello-openshift
    spec:
      containers:
      - name: hello-openshift
        image: openshift/hello-openshift
        ports:
        - containerPort: 8080
          protocol: TCP
        resources:
          requests:
            cpu: 300m
            memory: 64Mi
          limits:
            cpu: 600m
            memory: 128Mi
  1. 查看hello-deployment.yml文件,注意执行hello-openshift.yml对应的目录。
- hosts: localhost
  gather_facts: false
  vars_files:
  - mysecrets
  - myvars
  
  tasks:
  - name: Try to login to OCP cluster
    k8s_auth:
      host: "{{ ocp_master }}"
      username: "{{ ocp_username }}"
      password: "{{ ocp_password }}"
      validate_certs: no
    register: k8s_auth_result
    
  - name: Create a Deployment by reading the definition from a local file
    k8s:
      namespace: testing
      state: present
      src: ~/ansible/hello-openshift.yml
      api_key: "{{ k8s_auth_result.k8s_auth.api_key }}"
  1. 运行Ansible脚本。
$ ansible-playbook --vault-id=decrypt_passwd hello-deployment.yml
 
PLAY [localhost] ***********************************************************************************************************************************
 
TASK [Try to login to OCP cluster] ***********************************************************************************************************************************
ok: [localhost]
 
TASK [Create a k8s namespace] ***********************************************************************************************************************************
changed: [localhost]
 
TASK [Create a Deployment by reading the definition from a local file] ***********************************************************************************************************************************
changed: [localhost]
 
PLAY RECAP ***********************************************************************************************************************************
localhost                  : ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
  1. 确认对象创建成功。
 oc get all -n testing
NAME                                  READY   STATUS    RESTARTS   AGE
pod/hello-openshift-5f5c9bc6f-9xvwv   1/1     Running   0          41s
 
NAME                              READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/hello-openshift   1/1     1            1           41s
 
NAME                                        DESIRED   CURRENT   READY   AGE
replicaset.apps/hello-openshift-5f5c9bc6f   1         1         1       41s

查看Pod对象列表

  1. 查看pod-list.yml文件,它使用了k8s_info查看Pod的名称。
- hosts: localhost
  gather_facts: false
  vars_files:
  - mysecrets  
  - myvars

  tasks:
  - name: Try to login to OCP cluster
    k8s_auth:
      host: "{{ ocp_master }}"
      username: "{{ ocp_username }}"
      password: "{{ ocp_password }}"
      validate_certs: no
    register: k8s_auth_result

  - name: Get a list of all pods from testing
    k8s_info:
      namespace: testing
      api_key: "{{ k8s_auth_result.k8s_auth.api_key }}"
      kind: Pod
    register: pod_list
    
  - name: Print pod list
    debug:
      msg: "pod_list: {{ pod_list | json_query('resources[*].metadata.name')  }}"
  1. 执行命令运行pod-list.yml,然后查看输出的pod名称。
$ ansible-playbook --vault-id=decrypt_passwd pod-list.yml
。。。
TASK [Print pod list] **************************************************************************************************************************
ok: [localhost] =>
  msg: 'pod_list: [''hello-openshift-5f5c9bc6f-9xvwv''] '
。。。

删除Pod

  1. 查看del-pod.yml文件。
- hosts: localhost
  gather_facts: false
  vars_files:
  - mysecrets  
  - myvars

  tasks:
  - name: Try to login to OCP cluster
    k8s_auth:
      host: "{{ ocp_master }}"
      username: "{{ ocp_username }}"
      password: "{{ ocp_password }}"
      validate_certs: no
    register: k8s_auth_result

  - name: Get a list of all pods from testing
    k8s_info:
      namespace: testing
      api_key: "{{ k8s_auth_result.k8s_auth.api_key }}
      kind: Pod
    register: pod_list

  - name:  Delete pods
    k8s:
      state: absent
      api_version: v1
      kind: Pod
      namespace: testing
      api_key: "{{ k8s_auth_result.k8s_auth.api_key }}
      name: "{{ item }}"
    loop: "{{ pod_list | json_query('resources[*].metadata.name') }}"
  1. 执行命令运del-pod.yml脚本,删除pod。查看执行结果,注意当前的Pod已经被删除。
$ ansible-playbook --vault-id=decrypt_passwd del-pod.yml
。。。
TASK [Delete pods] ***********************************************************************************************************************************
changed: [localhost] => (item=hello-openshift-5f5c9bc6f-9xvwv)
。。。
  1. 查看pod,确认原有pod被删除。不过OpenShift会创建新的Pod替代它。
$ oc get pod
NAME                              READY   STATUS              RESTARTS   AGE
hello-openshift-5f5c9bc6f-9xvwv   0/1     Terminating         0          64m
hello-openshift-5f5c9bc6f-mzvjs   0/1     ContainerCreating   0          6s

参考

https://docs.ansible.com/ansible/latest/modules/k8s_module.html

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值