我使用gitlab-ci进行自动化测试。现在,我将其扩展到允许通过一个安全的剧本部署在数字海洋飞沫上的评论应用程序。
这非常有效,但是我需要从ansible到.gitlab-ci获取一个变量 - 我无法找到它的方法。
.gitlab-ci.yml
Deploy for Review:
before_script: []
stage: review
script: 'cd /home/playbooks/oewm/deployment && ansible-playbook -i inventories/review --extra-vars "do_name=$CI_PIPELINE_ID api_git_branch=$CI_BUILD_REF_NAME" digitalocean.yml'
environment:
name: review/$CI_BUILD_REF_NAME
url: http://$IP_FROM_ANSIBLE
on_stop: "Stop Review"
only:
- branches
when: manual
tags:
- deploy
剧本中的相关部分:
- name: Create DO Droplet
delegate_to: localhost
local_action:
module: digital_ocean
state=present
command=droplet
name=review-{{ do_name }}
api_token={{ do_token }}
region_id={{ do_region }}
image_id={{ do_image }}
size_id={{ do_size }}
ssh_key_ids={{ do_ssh }}
wait_timeout=500
register: my_droplet
- name: print info about droplet
delegate_to: localhost
local_action:
module: debug
msg="ID is {{ my_droplet.droplet.id }} IP is {{ my_droplet.droplet.ip_address }}"
那么如何才能将gletlab-ci的Droplet ID和IP? (稍后的停止操作需要ID,要向开发人员查看IP)
答案 0 :(得分:3)
Ansible是一个YAML配置的脚本工具本身,可能几乎完全自动化脚本环境本身。为什么不让它在某处写一个名为“./ip_address.sh”的文件,然后将.sh包含在你的gitlab CI中?
所有这一切的最高级别,在.gitlab-ci.yml
中会有:
script:
- ./run_ansible.sh ./out/run_file_generated_from_ansible.sh
- . ./out/run_file_generated_from_ansible.sh
- echo $IP_FROM_ANSIBLE
environment:
name: review/$CI_BUILD_REF_NAME
url: http://$IP_FROM_ANSIBLE
on_stop: "Stop Review"
将上面的两个shell脚本编写为读者的练习。魔法发生在Ansible“playbook”里面,它实际上只是一个脚本,你用文件名“./out/run_file_generate_from_ansible.sh”“将变量导出到磁盘”。
你没有说清楚的是你需要在Gitlab-CI中使用该变量以及最终结果,以及接下来会发生什么。所以上面,我只是展示了一种可以通过临时磁盘文件(IP地址)“导出”的方法。
您可以将该导出值保存为工件并在其他阶段捕获它,因此如果将所有这些工具放在名为./out
的目录中,则可以在各阶段之间传递这种“工件导出”。在gitlab-ci.yml中声明一个artifacts语句。
答案 1 :(得分:1)
我终于得到了运行的设置。我的解决方案使用AWS Route53生成动态主机名。 (我忽略了一个问题 - 我需要不同评论应用的主机名)
第1步:
动态构建主机名。为此,我使用了$CI_PIPELINE_ID
我在Route53上创建了一个子域,我们将其称为review.mydomain.com
。 Ansible Playbook从create_droplet获取IP,并使用Pipeline id在Route53上创建记录。 1234.review.mydomain.com
。
现在我的.gitlab-ci.yml知道这个主机名(因为它可以随时构建它) - 不再需要将Digitalocean Droplet IP从ansible skript中取出。
第2步: 审查后 - 用户应该能够停止/销毁液滴。为此,我需要在创建此Droplet时获得的Droplet ID。 但是破坏是一个不同的剧本,将在稍后播放 - 由开发人员调用 所以我需要一种在某处存储变量的方法 但是等等,现在我知道它是哪个主机,我可以在这个主机上创建一个事实文件,为我存储ID。当我需要摧毁主人时,ansible向我提供了事实,我知道身份证。
在剧本中它看起来像这样:角色:digitalocean
---
- name: Create DO Droplet
delegate_to: localhost
local_action:
module: digital_ocean
state=present
command=droplet
name=oewm-review-{{ do_name }}
api_token={{ do_token }}
region_id={{ do_region }}
image_id={{ do_image }}
size_id={{ do_size }}
ssh_key_ids={{ do_ssh }}
wait_timeout=500
register: my_droplet
- name: print info about droplet
delegate_to: localhost
local_action:
module: debug
msg="DO-ID:{{ my_droplet.droplet.id }}"
- name: print info about droplet
delegate_to: localhost
local_action:
module: debug
msg="DO-IP:{{ my_droplet.droplet.ip_address }}"
# DNS
- name: Get existing host information
route53:
command: get
zone: "{{ r53_zone }}"
record: "{{ do_name }}.review.mydomain.com"
type: A
aws_access_key: "{{ r53_access_key }}"
aws_secret_key: "{{ r53_secret_key }}"
register: currentip
- name: Add DNS Record for Web-Application
route53:
command: create
zone: "{{ r53_zone }}"
record: "{{ do_name }}.review.mydomain.com"
type: A
ttl: 600
value: "{{ my_droplet.droplet.ip_address }}"
aws_access_key: "{{ r53_access_key }}"
aws_secret_key: "{{ r53_secret_key }}"
when: currentip.set.value is not defined
- name: Add DNS Record for API
route53:
command: create
zone: "{{ r53_zone }}"
record: "api.{{ do_name }}.review.mydomain.com"
type: A
ttl: 600
value: "{{ my_droplet.droplet.ip_address }}"
aws_access_key: "{{ r53_access_key }}"
aws_secret_key: "{{ r53_secret_key }}"
when: currentip.set.value is not defined
- name: Add new droplet to host group
add_host:
hostname: "{{ my_droplet.droplet.ip_address }}"
groupname: api,web-application
ansible_user: root
api_domain: "api.{{ do_name }}.review.mydomain.com"
app_domain: "{{ do_name }}.review.mydomain.com"
- name: Wait until SSH is available on {{ my_droplet.droplet.ip_address }}
local_action:
module: wait_for
host: "{{ my_droplet.droplet.ip_address }}"
port: 22
delay: 5
timeout: 320
state: started
Playbook digitalocean.yml:
---
- name: Launch DO Droplet
hosts: all
run_once: true
gather_facts: false
roles:
- digitalocean
- name: Store Facts
hosts: api
tasks:
- name: Ensure facts directory exists
file:
path: "/etc/ansible/facts.d"
state: directory
- name: store variables on host for later fact gathering
template:
src={{ playbook_dir }}/roles/digitalocean/templates/digitalocean.fact.js2
dest="/etc/ansible/facts.d/digitalocean.fact"
mode=0644
- name: Deploy
hosts: api
roles:
- deployroles
Playbook digitalocean_destroy.yml:
- name: Add Host to Inventory
hosts: all
vars:
r53_zone: review.mydomain.com
r53_access_key: "xxxx"
r53_secret_key: "xxxx"
tasks:
- name: Get existing DNS host information
route53:
command: get
zone: "{{ r53_zone }}"
record: "{{ do_name }}.review.mydomain.com"
type: A
aws_access_key: "{{ r53_access_key }}"
aws_secret_key: "{{ r53_secret_key }}"
register: currentip
- name: Remove DNS Record for Web-Application
route53:
command: delete
zone: "{{ r53_zone }}"
record: "{{ do_name }}.review.mydomain.com"
type: A
ttl: 600
value: "{{ my_droplet.droplet.ip_address }}"
aws_access_key: "{{ r53_access_key }}"
aws_secret_key: "{{ r53_secret_key }}"
when: currentip.set.value is defined
- name: Remove DNS Record for API
route53:
command: delete
zone: "{{ r53_zone }}"
record: "api.{{ do_name }}.review.mydomain.com"
type: A
ttl: 600
value: "{{ my_droplet.droplet.ip_address }}"
aws_access_key: "{{ r53_access_key }}"
aws_secret_key: "{{ r53_secret_key }}"
when: currentip.set.value is defined
- name: Add droplet to host group
add_host:
hostname: "{{ do_name }}.review.mydomain.com"
groupname: api,web-application
ansible_user: root
- name: Digitalocean
hosts: api
vars:
do_token: xxxxx
tasks:
- name: Delete Droplet
delegate_to: localhost
local_action:
module: digital_ocean
state=deleted
command=droplet
api_token={{ do_token }}
id="{{ ansible_local.digitalocean.DO_ID }}"
.gitlab-ci.yml的相关部分:
Deploy for Review:
before_script: []
stage: review
script:
- 'cd /home/playbooks/myname/deployment && ansible-playbook -i inventories/review --extra-vars "do_name=$CI_PIPELINE_ID api_git_branch=$CI_BUILD_REF_NAME" digitalocean.yml'
environment:
name: review/$CI_BUILD_REF_NAME
url: http://$CI_PIPELINE_ID.review.mydomain.com
on_stop: "Stop Review"
only:
- branches
when: manual
tags:
- deploy
Stop Review:
before_script: []
stage: review
variables:
GIT_STRATEGY: none
script:
- 'cd /home/playbooks/myname/deployment && ansible-playbook -i inventories/review --extra-vars "do_name=$CI_PIPELINE_ID" digitalocean_destroy.yml'
when: manual
environment:
name: review/$CI_BUILD_REF_NAME
action: stop
only:
- branches
tags:
- deploy
# STAGING
Deploy to Staging:
before_script: []
stage: staging
script:
- 'cd /home/playbooks/myname/deployment && ansible-playbook -i inventories/staging --extra-vars "api_git_branch=$CI_BUILD_REF_NAME" deploy.yml'
environment:
name: staging
url: https://staging.mydomain.com
when: manual
tags:
- deploy