Hiển thị các bài đăng có nhãn Vagrant. Hiển thị tất cả bài đăng
Hiển thị các bài đăng có nhãn Vagrant. Hiển thị tất cả bài đăng

Thứ Hai, 12 tháng 4, 2021

Cài đặt Docker trong Ubuntu 18.04

 Gói cài đặt Docker có sẵn trong kho(repository) chính thức của Ubuntu nhưng đó có thể không phải là phiên bản mới nhất. Để cài đặt phiên bản mới nhất của Docker, ta sẽ cài đặt nó từ kho chính thức của Docker. Để thực hiện điều này, ta sẽ thêm nguồn của package vào Ubuntu để nó biết tải Docker từ đâu, thêm khóa GPG từ Docker để đảm bảo Docker tải về là chính cống, rồi sau đó cài đặt gói này.

Nếu bạn ở hệ điều hành Windows và muốn dùng Docker trên Ubuntu, bạn có thể dùng Vagrant để tạo một máy ảo có hệ điều hành Ubuntu 18.04 chẳng hạn để cài Docker trên máy ảo này. Chi tiết dùng Vagrant tham khảo tại đây :

Cài đặt Vagrant trên Windows

 

Sau đây là các bước để cài đặt Docker trên Ubuntu :

Trước tiên, ta cập nhật danh sách các package:

$ sudo apt update 

 

Sau đó, cài đặt các package cần thiết để cho phép apt dùng package thông qua phương thức HTTPS :

$ sudo apt install apt-transport-https ca-certificates curl software-properties-common

 

Tiếp theo ta thêm khóa GPG của kho chính thức của Docker vào HĐH Ubuntu :

$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

Thêm kho Docker vào APT sources trong Ubuntu 18.04
$ sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu bionic stable"


Sau đó, cập nhật lại danh sách các gói, ta sẽ thấy gói Docker từ repo vừa được thêm vào này:
$ sudo apt update


Nhớ xem kỹ là ta cài Docker từ kho chính thức của Docker chứ không phải từ kho của Ubuntu :

$ apt-cache policy docker-ce

Ta có thể thấy xuất hiện như sau (phiên bản Docker có thể khác ít nhiều)
  Installed: (none)
  Candidate: 18.03.1~ce~3-0~ubuntu
  Version table:
     18.03.1~ce~3-0~ubuntu 500
        500 https://download.docker.com/linux/ubuntu bionic/stable amd64 Packages

Giờ đây, ta có thể cài đặt Docker :
$ sudo apt install docker-ce

 

Sau khi cài đặt, kiểm tra xem Docker có đang hoạt động :

$ sudo systemctl status docker


Để thực thi các lệnh Docker mà không cần sudo
 

Mặc định, ta phải là người dùng root hoặc người dùng trong group docker khi thực thi các lệnh docker. Để tránh phải đánh sudo mỗi lần thực thi lệnh docker, ta thêm tên người dùng (ở đây là vagrant chẳng hạn) vào nhóm docker :

$ sudo usermod -aG docker vagrant

Để cập nhật thông tin vừa thêm vào nhóm
$ su - vagrant


Kiểm tra xem người dùng vagrant đã được thêm vào nhóm docker :
$ id -nG
Hiển thị :
vagrant docker

 

Một số lệnh docker

Tạo một image Docker tên toan từ Dockerfile ở thư mục hiện hành

$ sudo docker build -t toan .


Liệt kê các containers docker

$ docker ps -a

 

Liệt kê các image Docker

$ docker images

 

Xóa một image Docker

$ docker image rm -f <id của image Docker>


Thứ Năm, 21 tháng 1, 2021

Cài đặt Oracle 11g XE trong Ubuntu bằng Ansible

 Xem thêm về cách dùng role Ansible tại đây : Tạo và dùng Role với Ansible

Việc cài đặt Oracle 11g cần có python(2 hoặc 3), unzip cài đặt sẵn như khi ta cài Tomcat 9 ở bài trên. Dưới đây ta sẽ tạo một role có tên oracle-server cho phép ta cài đặt, cấu hình và tạo một cơ sở dữ liệu, rồi gỡ cài đặt này (uninstall) nếu muốn. Oracle ta sẽ cài là Oracle 11g XE, ta có thể tải gói này về từ trang chính thức của Oracle (phải login vào để tải về). Ở đây tôi dùng một đường dẫn có sẵn trên mạng để tải gói này về. Ta phải chuyển định dạng gói này từ .rpm sang .deb để có thể cài đặt nó trong Ubuntu.

Cấu trúc thư mục role oracle-server như sau :

vagrant@ansible:~$ tree /vagrant/toan/
/vagrant/toan/
├── inventory-all-vms.yml
├── playbook-oracle-server.yml
└── roles
├── oracle-server
│   ├── defaults
│   │   └── main.yml
│   ├── tasks
│   │   ├── main.yml
│   │   ├── oracle-toan-configure.yml
│   │   ├── oracle-ubuntu-install.yml
│   │   └── oracle-ubuntu-uninstall.yml
│   └── templates
│   ├── addToanTables.sql.j2
│   ├── chkconfig.j2
│   ├── configureSystemParameters.sql.j2
│   ├── createUserToan.sql.j2
│   ├── modifyPassword.sql.j2
│   ├── oracle-toan-configure.j2
│   └── oracle-xe-conf.j2
├── python
│   └── tasks
│   └── main.yml
├── python3
│   └── tasks
│   └── main.yml
└── unzip
└── tasks
└── main.yml

Nội dung của role oracle-server như sau :

oracle-server\defaults\main.yml : tập tin này định nghĩa các biến dùng cho role oracle-server

---
oracleserver_url: "http://download.xskernel.org/soft/linux-rpm/oracle-xe-11.2.0-1.0.x86_64.rpm.zip"
oracleserver_package: "oracle-xe-11.2.0-1.0.x86_64.rpm"

toan_user: toan
toan_password: toan
oracle_sys_password: syspwd
oracle_system_password: manager
config_file_path: /tmp/oracleToan

oracle_install: True
oracle_toan_configure: True
oracle_uninstall: False

oracle_http_port: 8081
oracle_listener_port: 1521
oracle_system_pwd: sysadmin
oracle_start_boot: y

* oracle-server\tasks

oracle-server\tasks\main.yml

- name : uninstall oracle
include_tasks: oracle-ubuntu-uninstall.yml
when: oracle_uninstall == True

- name : install oracle
include_tasks: oracle-ubuntu-install.yml
when: oracle_install == True

- name : configure oracle for toan
include_tasks: oracle-toan-configure.yml
when: oracle_toan_configure == True

Ansible sẽ đọc tập tin này và thực hiện tuần tự các tác vụ được định nghĩa trong đó. Ở đây, tùy vào giá trị của các biến oracle_uninstall, oracle_install và oracle_toan_configure là True hay False mà ansible sẽ thực hiện các tác vụ định nghĩa trong những tập tin tương ứng.

Giá trị mặc định của các biến này được định nghĩa là oracle_install: True; oracle_toan_configure: True . Vậy mặc định khi ta thực hiện lệnh ansible-playbook, ansible sẽ cài đặt oracle và tạo một CSDL như định nghĩa trong tập tin oracle-toan-configure.yml


oracle-server\tasks\oracle-ubuntu-install.yml

- name: install "yum", "libaio1", "bc", "alien"
become: yes
apt:
name: ["yum", "libaio1", "bc", "alien"]
state: latest
force_apt_get: yes

- name: download and unarchive {{ oracleserver_url }}
become: yes
unarchive:
src: "{{ oracleserver_url }}"
dest: "/tmp"
remote_src: yes

- name: Convert package {{ oracleserver_package }} to oracle-xe_11.2.0-2_amd64.deb
become: yes
shell: cd /tmp/Disk1 && alien --scripts --veryverbose {{ oracleserver_package }} >> /tmp/oracle-convert.log

- name: Copy work around /sbin/chkconfig file
become: yes
template:
src: templates/chkconfig.j2
dest: /sbin/chkconfig
mode: 0755

- name: Give permissions to oracle-xe_11.2.0-2_amd64.deb
become: yes
file:
path: "/tmp/Disk1/oracle-xe_11.2.0-2_amd64.deb"
mode: a+xrw

- name: install oracle-xe_11.2.0-2_amd64.deb
become: yes
apt:
deb: /tmp/Disk1/oracle-xe_11.2.0-2_amd64.deb

- name: Copy oracle config file
become: yes
template:
src: templates/oracle-xe-conf.j2
dest: /tmp/oracle-xe.conf
mode: 0755

- name: Test if execution of oracle_env.sh is already added in /etc/bash.bashrc
shell: grep -c "^/u01/app/oracle/product/11.2.0/xe/bin/oracle_env.sh" /etc/bash.bashrc || true
register: test_oracle_env

- name: add oracle environement variables by adding execution of oracle_env.sh in /etc/bash.bashrc
become: yes
lineinfile:
dest: /etc/bash.bashrc
line: ". /u01/app/oracle/product/11.2.0/xe/bin/oracle_env.sh"
when: test_oracle_env.stdout == "0"

- name: Export oracle environnement variables by executing /u01/app/oracle/product/11.2.0/xe/bin/oracle_env.sh
become: yes
shell: . /u01/app/oracle/product/11.2.0/xe/bin/oracle_env.sh

- name: configure oracle-xe
become: yes
shell: /etc/init.d/oracle-xe configure < /tmp/oracle-xe.conf >> /tmp/oracle-xe.log

- name: Start Oracle-xe service
become: yes
shell: /etc/init.d/oracle-xe start

#- name: Add start oracle-xe service at boot
# become: yes
# shell: update-rc.d oracle-xe defaults

Tập tin này định nghĩa các bước để cài đặt Oracle 11g XE. Cụ thể là :
- Cài đặt những thư viện mà oracle cần dùng.
- Tải về gói rpm để cài oracle và giải nén nó.
- Chuyển gói rpm thành gói deb để có thể cài đặt nó trong Ubuntu.
- Tạo tập tin chkconfig nhằm cho phép cấu hình oracle khởi động khi boot và chép nó vào /sbin/chkconfig . Đây là cách hack để sử dụng lệnh "update-rc.d oracle-xe defaults" vì chkconfig không còn được dùng trong Ubuntu nữa mà quá trình cài đặt của gói oracle lại dùng đến chkconfig.
- Cài gói .deb vừa tạo
- Thực hiện lệnh "configure oracle-xe" để cấu hình oracle vừa cài đặt, nội dung thông tin cần trả lời cho quá trình cài đặt này được định nghĩa trong tập tin oracle-xe.conf
- Sau cùng là khởi động oracle một khi đã cài đặt xong.


oracle-server\tasks\oracle-toan-configure.yml : 

- name: Create {{ config_file_path }}
file:
path: "{{ config_file_path }}"
state: directory
mode: "u+rwx,g+rwx,o=rwx"
recurse: yes

- name: Copy oracle-toan-configure.sh file to {{ config_file_path }}
become: yes
template:
src: templates/oracle-toan-configure.j2
dest: "{{ config_file_path }}/oracle-toan-configure.sh"
mode: 0755

- name: Copy modifyPassword.sql file to {{ config_file_path }}
become: yes
template:
src: templates/modifyPassword.sql.j2
dest: "{{ config_file_path }}/modifyPassword.sql"
mode: 0755

- name: Copy createUserToan.sql file to {{ config_file_path }}
become: yes
template:
src: templates/createUserToan.sql.j2
dest: "{{ config_file_path }}/createUserToan.sql"
mode: 0755

- name: Copy configureSystemParameters.sql file to {{ config_file_path }}
become: yes
template:
src: templates/configureSystemParameters.sql.j2
dest: "{{ config_file_path }}/configureSystemParameters.sql"
mode: 0755

- name: Copy addToanTables.sql file to {{ config_file_path }}
become: yes
template:
src: templates/addToanTables.sql.j2
dest: "{{ config_file_path }}/addToanTables.sql"
mode: 0755

- name: update oracle user password
become: yes
user:
name: oracle
password: "{{ 'oracle' | password_hash('sha512') }}"

- name: configure oracle for toan
become: yes
become_user: oracle
shell: "{{ config_file_path }}/oracle-toan-configure.sh"
args:
chdir: "{{ config_file_path }}"

Tập tin này định nghĩa việc thực hiện việc cấu hình và tạo một CSDL cho user toan, nó sẽ gọi đến tập tin oracle-toan-configure.sh để thực thi các script sql trong thư mục templates.


oracle-server\tasks\oracle-ubuntu-uninstall.yml

- name: Stop Oracle-xe service
become: yes
service:
name: "oracle-xe"
state: stopped

- name: Create archive directory /dev/rmt0
file:
path: /dev/rmt0
state: directory
mode: "u+rwx,g+rwx,o=rwx"
recurse: yes

- name: Compress directory /u01/app/oracle into /dev/rmt0/oracle-bkup.tgz
archive:
path: /u01/app/oracle
dest: /dev/rmt0/oracle-bkup.tgz

- name: Remove oracle-xe package
become: yes
apt:
name: oracle-xe
state: absent
purge: yes

- name: Clean up /u01
become: yes
file:
path: /u01
state: absent

- name: Clean up /etc/oratab
become: yes
file:
path: /etc/oratab
state: absent

- name: Delete /etc/init.d/oracle-xe
become: yes
file:
path: /etc/init.d/oracle-xe
state: absent

- name: Delete /etc/default/oracle-xe
become: yes
file:
path: /etc/default/oracle-xe
state: absent

- name: Delete {{ config_file_path }}
become: yes
file:
path: "{{ config_file_path }}"
state: absent

- name: Remove the start of oracle-xe service at boot
become: yes
shell: update-rc.d -f oracle-xe remove

Tập tin này định nghĩa các bước để backup rồi xóa oracle (uninstall) 

 

* oracle-server\templates

Các script SQL để cấu hình CSDL cho user toan

oracle-server\templates\modifyPassword.sql.j2

set echo on
spool ./modifyPassword.log

alter profile default LIMIT PASSWORD_LIFE_TIME UNLIMITED;

alter user system identified by {{ oracle_system_password }};
alter user sys identified by {{ oracle_sys_password }};
commit;

spool off
exit 0

 

oracle-server\templates\configureSystemParameters.sql.j2

set echo on
spool ./configureSystemParameters.log

alter system set processes=1200 scope=spfile;
alter system set sessions=1822 scope=spfile;
alter system set transactions=3000 scope=spfile;
alter system set open_cursors=4000 scope=spfile;

spool off
exit 0

 

oracle-server\templates\createUserToan.sql.j2

set echo on
spool ./createUserToan.log

create user {{ toan_user }} identified by {{ toan_password }};
grant connect to {{ toan_user }};
grant resource to {{ toan_user }};
grant exp_full_database to {{ toan_user }};
grant imp_full_database to {{ toan_user }};
alter user {{ toan_user }} default tablespace TOAN_MDATA;
commit;

spool off
exit 0

oracle-server\templates\addToanTables.sql.j2

set echo on
spool ./addToanTables.log

drop table USER_LOGIN cascade constraints;

create table USER_LOGIN (
login varchar2(255) not null,
password varchar2(255),
primary key (login)
);

insert into USER_LOGIN (LOGIN, PASSWORD) values ('toan','test');

spool off
exit 0

Các tập tin lệnh bash và cấu hình

oracle-server\templates\oracle-xe-conf.j2

{{ oracle_http_port }}
{{ oracle_listener_port }}
{{ oracle_system_pwd }}
{{ oracle_system_pwd }}
{{ oracle_start_boot }}

Tập tin này được dùng trong lúc cấu hình oracle lần đầu tiên bằng lệnh "configure oracle-xe" như ta thấy ở trên.

 

oracle-server\templates\chkconfig.j2

#!/bin/bash
# Oracle 11gR2 XE installer chkconfig work around for Ubuntu

file=/etc/init.d/oracle-xe
if [[ ! `tail -n1 $file | grep INIT` ]]; then
cat >> $file <<-EOM
#
### BEGIN INIT INFO
# Provides: OracleXE
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Oracle 11g Express Edition
### END INIT INFO
EOM
fi

case "$1" in
--add)
echo "Add start oracle-xe service at boot"
update-rc.d oracle-xe defaults
;;
--del)
echo "Remove the start of oracle-xe service at boot"
update-rc.d -f oracle-xe remove
;;
esac
exit 0

Tập tin này cấu hình việc khởi động tự động oracle khi boot. Nó được chép vào /sbin/chkconfig và sẽ được gọi đến khi cài hoặc xóa oracle.


oracle-server\templates\oracle-toan-configure.j2

#!/bin/bash

. /u01/app/oracle/product/11.2.0/xe/bin/oracle_env.sh

START_TIME=$SECONDS
echo BEGIN: `date "+%Y-%m-%d %H:%M:%S"`

sqlplus '/ as sysdba' @ {{ config_file_path }}/modifyPassword.sql
sqlplus system/{{ oracle_system_password }} @ {{ config_file_path }}/configureSystemParameters.sql

sqlplus '/ as sysdba' @ {{ config_file_path }}/createUserToan.sql
sqlplus {{ toan_user }}/{{ toan_password }} @ {{ config_file_path }}/addToanTables.sql

echo END: `date "+%Y-%m-%d %H:%M:%S"`
ELAPSED_TIME=$(($SECONDS - $START_TIME))
echo "DURATION=$ELAPSED_TIME seconds"
exit 0

Tập tin này định nghĩa việc thực thi các script sql để cấu hình và tạo một CSDL cho user toan.


* Các tập tin inventory và playbook

inventory-all-vms.yml

all:
children:
ubuntu_servers:
hosts:
jenkins_ubuntu18:
ansible_host: 10.0.0.11

toan_local:
hosts:
toan_ubuntu16:
ansible_host: 10.0.0.12

Trên đây là tập tin inventory định nghĩa các host  

 

playbook-oracle-server.yml

- name: Content of all VMs
hosts: toan_ubuntu16
become: yes
roles:
- { role: ./roles/unzip }
- { role: ./roles/python3 }
- { role: ./roles/python }

- name: Content of all parkfolio servers
hosts: toan_ubuntu16
become: yes
roles:
- { role: ./roles/oracle-server }

Trên đây là tập tin playbook để thực hiện việc cài đặt/cấu hình/xóa oracle.

 

* Tập tin Vagrantfile định nghĩa các máy ảo như sau : 

Vagrant.configure("2") do |config|

#common part of vms
BOX_IMAGE = "ubuntu/bionic64" # bionic 64 = ubuntu 18.04 64 bits

#ansible vm description
config.vm.define "ansible" do |ansible|
ansible.vm.box = BOX_IMAGE
ansible.vm.hostname = "ansible"
ansible.vm.network "private_network", ip: "10.0.0.10", virtualbox__intnet: true
ansible.vm.provision "shell", inline: "apt install python -yq", privileged: true
ansible.vm.provision "shell", inline: "sudo apt-get install -yq software-properties-common", privileged: true
ansible.vm.provision "shell", inline: "sudo apt-add-repository -y ppa:ansible/ansible", privileged: true
ansible.vm.provision "shell", inline: "sudo apt-get update -yq", privileged: true
ansible.vm.provision "shell", inline: "sudo apt-get install -yq ansible", privileged: true
ansible.vm.provision "shell", inline: "sudo apt-get install -yq mc", privileged: true
end

#jenkins vm description
config.vm.define "jenkins" do |jenkins|
jenkins.vm.box = BOX_IMAGE
jenkins.vm.hostname = "jenkins"
jenkins.vm.network "private_network", ip: "10.0.0.11", virtualbox__intnet: true
jenkins.vm.provision "shell", inline: "sudo apt-get install -yq mc", privileged: true
end

config.vm.define "toan" do |toan|
toan.vm.box = "ubuntu/xenial64"
toan.vm.hostname = "toan"
toan.disksize.size = '10GB'
toan.vm.network "private_network", ip: "10.0.0.12", virtualbox__intnet: true
toan.vm.network "forwarded_port", guest: 8084, host: 8084
toan.vm.network "forwarded_port", guest: 1521, host: 1524
toan.vm.provision "shell", inline: "sudo apt-get install -yq mc", privileged: true
end

# Provider-specific configuration
config.vm.provider "virtualbox" do |v|
v.memory = "1024"
end

end

 

* Cài đặt Oracle 11g XE trong Ubuntu có thể tóm gọn vào các lệnh sau :

vagrant@toan:~$ sudo apt-get install unzip
vagrant@toan:~$ sudo apt-get install alien
vagrant@toan:~$ sudo apt-get install libaio1
vagrant@toan:~$ cd /tmp
vagrant@toan:/tmp$ wget http://download.xskernel.org/soft/linux-rpm/oracle-xe-11.2.0-1.0.x86_64.rpm.zip
vagrant@toan:/tmp$ unzip oracle-xe-11.2.0-1.0.x86_64.rpm.zip
vagrant@toan:/tmp$ cd /tmp/Disk1
vagrant@toan:/tmp/Disk1$ sudo alien --scripts --veryverbose oracle-xe-11.2.0-1.0.x86_64.rpm >> convert-oracle.log
vagrant@toan:/tmp/Disk1$ sudo cp /vagrant/toan/roles/oracle-server/templates/chkconfig.j2 /sbin/chkconfig
vagrant@toan:/tmp/Disk1$ sudo chmod 755 /sbin/chkconfig
vagrant@toan:/tmp/Disk1$ sudo dpkg --install ./oracle-xe_11.2.0-2_amd64.deb
vagrant@toan:~$ . /u01/app/oracle/product/11.2.0/xe/bin/oracle_env.sh
vagrant@toan:~$ sudo /etc/init.d/oracle-xe configure < /tmp/oracle-xe.conf >> /tmp/oracle-xe.log
vagrant@toan:~$ sudo /etc/init.d/oracle-xe start

* Xóa Oracle có thể tóm gọn như sau

$ sudo apt-get --remove oracle-xe
$ sudo apt-get --purge oracle-xe


Thứ Tư, 20 tháng 1, 2021

Tạo và dùng Role với Ansible - Cài đặt Tomcat 9 trong Ubuntu với Ansible

Xem thêm về cách dùng Ansible tại đây: Giới thiệu Ansible

1. Role trong Ansible là gì?

Trong Ansible, role là một cơ chế cho phép chia nhỏ một playbook thành nhiều tập tin. Điều này giúp đơn giản hóa khi ta muốn viết một playbook phức tạp và giúp ta tái sử dụng chúng.

Một role chỉ nên giới hạn trong việc thực hiện một tác vụ trọn vẹn với đầy đủ những bước để hoàn tất nó. Ngoài ra, nó cũng có thể gọi đến những role mà nó phụ thuộc nếu cần.

Chẳng hạn, ta muốn tạo một playbook để cài đặt Tomcat 9 trong Ubuntu. Và Tomcat cần có Java để hoạt động. Trong trường hợp này, ta sẽ tạo hai role, một để cài đặt Java 11 và một để cài đặt Tomcat. Trong role Tomcat ta sẽ gọi đến role Java để cài Java trước khi cài Tomcat.

Role không phải là playbook. Role chỉ là những tác vụ nhỏ có thể được thực thi một cách độc lập bên trong một playbook. Ta không thể trực tiếp thực thi role, và nó cũng không trực tiếp cho biết nó sẽ được áp dụng vào host nào. Như vậy playbook sẽ gọi đến để thực thi các role và tập tin inventory sẽ xác định các host mà role sẽ thực thi trên đó.


2. Cấu trúc của một role

Thư mục chứa các tập tin của một role có cấu trúc được quy ước bởi Ansible. Các role được tạo bên trong thư mục có tên "roles" nằm cùng thư mục với tập tin playbook. Tên của một role là tên của thư mục chứa role đó.

Chẳng hạn ta có thể tạo một thư mục role có tên tomcat9 với lệnh sau :

$ ansible-galaxy init tomcat9 
hoặc 
$ ansible-galaxy init --force --offline tomcat9 

Role tomcat9 vừa phát sinh này có cấu trúc như sau :
$ tree tomcat9/
tomcat9/
├── README.md
├── defaults
│   └── main.yml
├── files
├── handlers
│   └── main.yml
├── meta
│   └── main.yml
├── tasks
│   └── main.yml
├── templates
├── tests
│   ├── inventory
│   └── test.yml
└── vars
└── main.yml

8 directories, 8 files

Một role không nhất thiết phải có tất cả các thư mục như trên. Role đơn giản nhất chỉ cần có thư mục tasks. Tập tin main.yml trong thư mục này định nghĩa các tác vụ cho role.

Chú thích :

- tasks/main.yml : định nghĩa các tác vụ cho role thực thi

- handlers/main.yml : các handlers có thể được dùng bên trong hoặc bên ngoài role.

- defaults/main.yml : định nghĩa các biến mặc định dùng trong role. Các biến này có quyền ưu tiên thấp nhất và có thể được định nghĩa lại bên ngoài role.

- files/: chứa các tập tin mà role dùng trong việc thực thi nó.

- templates/: chứa các tập tin template dùng trong việc triển khai role. Các templates này có thể dùng cú pháp của Jinja2 để tham chiếu đến các biến định nghĩa trong ansible.

- meta/main.yml : định nghĩa những role mà role này phụ thuộc. Các role được định nghĩa ở đây sẽ được thực thi trước tiên, sau đó mới thực thi các tác vụ trong role hiện hành.

Một khi ta đã định nghĩa xong role tomcat9, ta sẽ tạo một playbook để thực thi role này như sau :

- name: Content of toan_ubuntu16
hosts: toan_ubuntu16
become: yes
roles:
- { role: ./roles/tomcat9 }

Dưới đây là một ví dụ cụ thể về việc dùng role với Ansible.



3. Cài đặt Tomcat 9 bằng Ansible

Việc cài đặt Tomcat 9 cần có java, python(2 hoặc 3), unzip cài đặt sẵn nên dưới đây ta cũng tạo các role này. Cụ thể cấu trúc các thư mục và tập tin cần tạo ta có như sau :

vagrant@ansible:~$ tree /vagrant/toan/
/vagrant/toan/
├── inventory-all-vms.yml
├── playbook-tomcat.yml
└── roles
├── open-jdk-11
│   └── tasks
│   └── main.yml
├── python
│   └── tasks
│   └── main.yml
├── python3
│   └── tasks
│   └── main.yml
├── tomcat9
│   ├── defaults
│   │   └── main.yml
│   ├── handlers
│   │   └── main.yml
│   ├── meta
│   │   └── main.yml
│   ├── tasks
│   │   └── main.yml
│   └── templates
│   └── tomcat9.service.j2
└── unzip
└── tasks
└── main.yml

15 directories, 11 files

 

Nội dung các tập tin trên như sau :

* Role open-jdk-11

open-jdk-11\tasks\main.yml :

---
- name: add openjdk repository
become: yes
apt_repository:
repo: ppa:openjdk-r/ppa
state: present

- name: install openjdk 11
become: yes
apt:
name: openjdk-11-jdk
state: present

- name: install openjre 11
become: yes
apt:
name: openjdk-11-jre
state: present

* Role python

python\tasks\main.yml :

- name: ensure python-dev is the latest version
become: yes
apt:
name: ["python", "python-pip", "python-setuptools", "python-dev", "python-dev", "build-essential", "libssl-dev", "libffi-dev", "libxml2-dev", "libxslt1-dev", "zlib1g-dev", "python-lxml"]
state: latest
force_apt_get: yes

* Role python3

python3\tasks\main.yml :

- name: ensure python3-dev is the latest version
become: yes
apt:
name: ["python3", "python3-pip", "python3-setuptools", "python-dev", "python3-dev", "build-essential", "libssl-dev", "libffi-dev", "libxml2-dev", "libxslt1-dev", "zlib1g-dev", "python3-lxml", "python3-pexpect"]
state: latest
force_apt_get: yes

* Role unzip

unzip\tasks\main.yml:

---
- name: install package
become: yes
apt:
name: unzip
state: present

* Role tomcat9

tomcat9\defaults\main.yml : tập tin này định nghĩa các biến dùng cho role tomcat9

tomcat9_service: "tomcat9"
tomcat9_server_root: "/etc/tomcat9"
tomcat9_conf_path: "/etc/tomcat9"
tomcat9_home: "/usr/share/tomcat9"
tomcat9_archive_url: "https://mirror.ibcp.fr/pub/apache/tomcat/tomcat-9/v9.0.41/bin/apache-tomcat-9.0.41.tar.gz"

tomcat9_user: "tomcat9"
tomcat9_port: "8084"
tomcat9_group: "{{ tomcat9_user }}"
tomcat9_webapps_dir: "/usr/share/tomcat9/webapps/"
tomcat9_config_server_file: "/usr/share/tomcat9/conf/server.xml"

tomcat9_logs_dir: "/usr/share/tomcat9/logs"

 

tomcat9\handlers\main.yml :

---
- name: start tomcat9
become: yes
service:
name: "{{ tomcat9_service }}"
state: started

- name: restart tomcat9
become: yes
service:
name: "{{ tomcat9_service }}"
state: restarted

- name: stop tomcat9
become: yes
service:
name: "{{ tomcat9_service }}"
state: stopped 

 

tomcat9\meta\main.yml :

---
dependencies:
- { role: open-jdk-11 }

Role tomcat9 phụ thuộc vào role open-jdk-11, do đó open-jdk-11 sẽ được cài đặt trước khi cài đặt tomcat 9

 

tomcat9\templates\tomcat9.service.j2

[Unit]
Description=Tomcat 9
After=syslog.target network.target

[Service]
Type=simple

User={{ tomcat9_user }}
Group={{ tomcat9_group }}

Environment=JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64
Environment='JAVA_OPTS=-Djava.awt.headless=true'

Environment=CATALINA_HOME=/usr/share/tomcat9
Environment=CATALINA_BASE=/usr/share/tomcat9

WorkingDirectory=/usr/share/tomcat9/bin

ExecStop=/bin/sh /usr/share/tomcat9/bin/catalina.sh stop
ExecStart=/bin/sh /usr/share/tomcat9/bin/catalina.sh run
UMask=0022
LogsDirectory=/usr/share/tomcat9/logs
LogsDirectoryMode=777
ReadWritePaths=/usr/share/tomcat9/webapps/

[Install]
WantedBy=multi-user.target

 

tomcat9\tasks\main.yml :

---
- name: add tomcat group
become: yes
group:
name: "{{ tomcat9_group }}"

- name: add tomcat user
become: yes
user:
name: "{{ tomcat9_user }}"
group: "{{ tomcat9_group }}"
home: "{{ tomcat9_home }}"
createhome: no

- name: Create a tomcat directory /usr/share/tomcat9
become: yes
file:
path: "{{ tomcat9_home }}"
state: directory
owner: "{{ tomcat9_user }}"
group: "{{ tomcat9_group }}"

- name: download and unarchive tomcat .tar.gz
become: yes
unarchive:
src: "{{ tomcat9_archive_url }}"
dest: "{{ tomcat9_home }}"
remote_src: yes
extra_opts: [--strip-components=1]

- name: Change ownership
become: yes
file:
path: "{{ tomcat9_home }}"
owner: "{{ tomcat9_user }}"
group: "{{ tomcat9_group }}"
mode: "u+rwx,g+rwx,o=rwx"
recurse: yes
state: directory

- name: Copy tomcat service file
become: yes
template:
src: templates/tomcat9.service.j2
dest: /etc/systemd/system/tomcat9.service
mode: 0644

- name: "configure server file {{ tomcat9_config_server_file }}"
xml:
path: "{{ tomcat9_config_server_file }}"
xpath: "/Server/Service[@name='Catalina']/Connector"
attribute: "port"
value: '{{ tomcat9_port }}'

- name: Create void catalina.out file and give permission
file:
path: /usr/share/tomcat9/logs/catalina.out
state: touch
mode: 0644

- name: Ensure logs are readable not only by tomcat9 user
become: yes
file:
path: "{{ tomcat9_logs_dir }}"
owner: root
group: root
state: directory
mode: a+xrw
recurse: yes

- name: Give permissions to work directory
file:
path: /usr/share/tomcat9/work
owner: root
group: root
mode: a+xrw
recurse: yes

- name: Give permissions to conf directory
file:
path: /usr/share/tomcat9/conf
owner: root
group: root
recurse: yes

- name: Create Catalina directory and give permission
file:
path: /usr/share/tomcat9/conf/Catalina
owner: "{{ tomcat9_user }}"
group: root
state: directory
mode: o+xrw
recurse: yes

- name: Give permissions to bin directory
file:
path: /usr/share/tomcat9/bin
owner: root
group: root
mode: a+xr
recurse: yes

- name: Give permissions to lib directory
file:
path: /usr/share/tomcat9/lib
owner: root
group: root
mode: a+xrw
recurse: yes

- name: Give permissions to webapps directory
file:
path: /usr/share/tomcat9/webapps
mode: a+xrw
recurse: yes

- name: Start and enable Tomcat service
systemd:
name: "{{ tomcat9_service }}"
state: started
enabled: yes
daemon_reload: yes

Tập tin trên định nghĩa quá trình cài đặt tomcat 9. Ở đây ta cài đặt Tomcat 9 trong Ubuntu 16.4 bằng cách tải gói tar.gz của nó về.

 

inventory-all-vms.yml

all:
children:
ubuntu_servers:
hosts:
jenkins_ubuntu18:
ansible_host: 10.0.0.11

toan_local:
hosts:
toan_ubuntu16:
ansible_host: 10.0.0.12

Trên đây là tập tin inventory định nghĩa các host 

 

playbook-tomcat.yml

- name: Content of all VMs
hosts: all
become: yes
roles:
- { role: ./roles/unzip }
- { role: ./roles/python3 }
- { role: ./roles/python }

- name: Content of toan_ubuntu16
hosts: toan_ubuntu16
become: yes
roles:
- { role: ./roles/tomcat9 }

Trên đây là tập tin playbook, nó sẽ thực hiện các role unzip, python, python3 trên tất cả các host. Nó chỉ thực thi role tomcat9 trên host toan_ubuntu16.

* Thực thi playbook này như sau :

vagrant@ansible:~$ ansible-playbook /vagrant/toan/playbook-tomcat.yml -i /vagrant/toan/inventory-all-vms.yml

 

* Tập tin Vagrantfile định nghĩa các máy ảo như sau :

Vagrant.configure("2") do |config|

#common part of vms
BOX_IMAGE = "ubuntu/bionic64" # bionic 64 = ubuntu 18.04 64 bits

#ansible vm description
config.vm.define "ansible" do |ansible|
ansible.vm.box = BOX_IMAGE
ansible.vm.hostname = "ansible"
ansible.vm.network "private_network", ip: "10.0.0.10", virtualbox__intnet: true
ansible.vm.provision "shell", inline: "apt install python -yq", privileged: true
ansible.vm.provision "shell", inline: "sudo apt-get install -yq software-properties-common", privileged: true
ansible.vm.provision "shell", inline: "sudo apt-add-repository -y ppa:ansible/ansible", privileged: true
ansible.vm.provision "shell", inline: "sudo apt-get update -yq", privileged: true
ansible.vm.provision "shell", inline: "sudo apt-get install -yq ansible", privileged: true
ansible.vm.provision "shell", inline: "sudo apt-get install -yq mc", privileged: true
end

#jenkins vm description
config.vm.define "jenkins" do |jenkins|
jenkins.vm.box = BOX_IMAGE
jenkins.vm.hostname = "jenkins"
jenkins.vm.network "private_network", ip: "10.0.0.11", virtualbox__intnet: true
jenkins.vm.provision "shell", inline: "sudo apt-get install -yq mc", privileged: true
end

config.vm.define "toan" do |toan|
toan.vm.box = "ubuntu/xenial64"
toan.vm.hostname = "toan"
toan.vm.network "private_network", ip: "10.0.0.12", virtualbox__intnet: true
toan.vm.network "forwarded_port", guest: 8084, host: 8084
toan.vm.provision "shell", inline: "sudo apt-get install -yq mc", privileged: true
end

end

Ở đây ta forward port của tomcat trong máy ảo là 8084 (định nghĩa trong lúc cài đặt tomcat ở trên) sang port 8084 của localhost. Sau khi thực hiện lệnh ansible-playbook như trên để cài đặt tomcat9, ta có thể kiểm tra tomcat có hoạt động hay chưa bằng URL sau :

http://localhost:8084/



Thứ Hai, 21 tháng 12, 2020

Giới thiệu Ansible

1. Ansible là gì?

Ansible là một công cụ cho phép tự động hóa việc triển khai (deploy) cài đặt các ứng dụng, thực hiện các tác vụ (task) và quản lý việc cấu hình (configuration) trên nhiều máy cùng lúc.

Ansible phân biệt hai loại máy (machine) hay còn gọi là node:
- Managed nodes hoặc hosts : Là những máy mà ta muốn cấu hình và cài đặt các ứng dụng trên chúng.
- Control node (máy điều khiển) : Ansible được cài đặt trên máy này ở hệ điều hành Linux, Windows không được hỗ trợ để làm control node. Máy này đọc các tập tin định nghĩa cấu hình và chạy Ansible để đẩy các cấu hình này vào các hosts.

Ansible dùng SSH để giao tiếp giữa máy điều khiển và các hosts. Ta cần cài đặt Python và SSH trên các nodes để có thể xài Ansible.


2. Một số khái niệm trong Ansible

- Inventory : là danh sách các hosts.

- Playbook : là tập tin định nghĩa các tác vụ cho Ansible và được viết bằng ngôn ngữ YAML. Nó định nghĩa các bước mà người dùng muốn thực thi trên một máy nào đó. Các tác vụ trong Playbook được thực thi tuần tự.

- YAML (là viết tắt của Yet Another Makeup Language và sau là YAML Ain't Markup Language) : là một ngôn ngữ đặc tả dễ hiểu cho người dùng.

- module : Khi bạn dùng Ansible là bạn dùng các module của Ansible. Các module này được viết bằng Python. Một số module của Ansible như file, apt, user...


3. Ansible hoạt động ra sao

Hình dưới đây miêu tả hoạt động của Ansible

                                             ________
______________ ssh | Host 1 |
| |--------------------->|________|
| | ssh ________
| Ansible |--------------------->| Host 2 |
| control node | |________|
| | ssh ________
|______________|--------------------->| Host n |
______|________ |________|
______|_____ _____|_____
| Playbook | | Inventory |
|____________| |___________|
host 1
host 2
host n

Khi dùng Ansible trên máy điều khiển (control node) ta sẽ cung cấp cho nó tập tin Playbook định nghĩa các tác vụ mà ta muốn thực thi tuần tự trên các host. Danh sách các host này được định nghĩa trong tập tin Inventory.

Ansible sẽ kết nối với các host và đẩy các tác vụ đến các nodes này. Sau đó Ansible thực thi tuần tự các modules định nghĩa trong các tác vụ này trên các host (thông qua kết nối SSH) để thực hiện các thao tác hoặc cài đặt một số phần mềm trên các host này. 

 

4. Căn bản về ngôn ngữ YAML dùng trong Ansible

Như đã nói ở trên Ansible dùng YAML để định nghĩa các tập tin playbook của nó vì ngôn ngữ này dễ hiểu với người dùng.

Mỗi tập tin YAML có thể bắt đầu bằng "---" và kết thúc bằng "..." nhưng điều này không bắt buộc.

YAML dùng cặp key-value để định nghĩa dữ liệu. Chú ý là phải có khoảng trắng sau : và value

Ví dụ : thông tin sinh viên

--- # Optional YAML start syntax
toan:
    name: toan
    number: 1
    sex: male
... # Optional YAML end syntax

Định nghĩa một danh sách trong YAML. Mỗi thành phần của danh sách được viết xuống hàng bắt đầu bằng "- " (- và một khoảng trắng). Các thành phần trong danh sách có cùng khoảng cách đầu dòng như nhau.

Ví dụ :

---
languages:
    - Java
    - Python
    - PHP
    - C++
...

Danh sách bên trong dictionary tức giá trị của một key trong cặp key-value là một danh sách
Ví dụ :

--- 
toan:
name: toan
number: 1
sex: male
    likes:
    - Java
    - Python
    - PHP
...

Danh sách các dictionary
Ví dụ:

--- 
- toan:
name: toan
number: 1
sex: male
likes:
- Java
- Python
- PHP

- tri:
name: tri
number: 2
sex: male
likes:
- C++
- HTML
- JavaScript
...

5. Cài đặt Ansible trên Ubuntu

Ta chỉ cần cài đặt Ansible trên một máy điều khiển tức control node. Máy này cần cài đặt Python 2 (phiên bản 2.7) hoặc Python 3 (phiên bản 3.5 trở lên). Hệ điều hành Windows không được hỗ trợ để làm control node cho Ansible. Trên các managed nodes cũng cần phải cài Python.

Dưới đây là lệnh cài đặt Ansible trên Ubuntu

  $ sudo apt update
  $ sudo apt install software-properties-common
  $ sudo apt-add-repository --yes --update ppa:ansible/ansible
  $ sudo apt install ansible

Sau khi cài xong Ansible, ta kiểm tra phiên bản vừa cài đặt bằng lệnh :
$ ansible --version

 

6. Tạo một tập tin Playbook cho Ansible

Trong tập tin playbook ta định nghĩa những tác vụ ta muốn tự động hóa. Ansible gọi danh sách các tác vụ này (task) là playbook.

Nếu ta định nghĩa hosts là all thì Ansible sẽ thực thi playbook trên toàn bộ các hosts một cách song song. Nhưng các tác vụ trong playbook sẽ được thực thi tuần tự, xong tác vụ này mới đến tác vụ kế tiếp.

Chú ý, cú pháp của YAML chú trọng thụt đầu dòng ngay ngắn và đều nhau, nên khi viết tập tin playbook ta cần chú ý việc thụt đầu dòng cho đúng. 

Dưới đây là nội dung tập tin playbook java11-setup.yml nhằm cài đặt java 11 trên toàn bộ các hosts.

---
- hosts: all
become: yes
vars:
packages:
- openjdk-11-jdk
- openjdk-11-jre
tasks:
- name: add openjdk repository
apt_repository:
repo: ppa:openjdk-r/ppa
state: present

- name: install openjdk 11
apt:
name: "{{ packages}}"
state: present

Giải thích :
- hosts: all : nói Ansible thực thi playbook này cho toàn bộ các host định nghĩa trong hosfile hoặc trong tập tin inventory.

- become: yes : thực hiện các lệnh này bằng sudo user. Xem tại đây https://docs.ansible.com/ansible/latest/user_guide/become.html

- vars: các biến variable định nghĩa bởi người dùng. Ngoài ra còn có một số nguồn biến khác, chẳng hạn như biến của hệ thống (system). Các biến hệ thống được gọi là fact.

- tasks: danh sách các tác vụ ta muốn thực thi.

Ta hãy xem tác vụ đầu tiên trong danh sách này :

  - name: add openjdk repository
apt_repository:
repo: ppa:openjdk-r/ppa
state: present
- name : mô tả ngắn gọn về tác vụ

- apt_repository: là module mà tác vụ này dùng để cấu hình và thực thi. Chi tiết về module này có thể xem tại đây
https://docs.ansible.com/ansible/latest/collections/ansible/builtin/apt_repository_module.html

Ansible cung cấp nhiều module định nghĩa sẵn. Module apt_repository cho phép thêm hoặc xóa một APT repository trong Ubuntu. Hầu hết các module có biến state để định nghĩa cho nó nên làm gì : present (thêm vào, khởi động hay thực thi), absent (xóa đi, dừng lại)

- repo : chuỗi định nghĩa repository

Module apt

Phần vars định nghĩa các package cần cài đặt

  vars: 
packages:
- openjdk-11-jdk
- openjdk-11-jre

tasks:
- name: install openjdk 11
apt:
name: "{{ packages}}"
state: present

Module apt quản lý các gói apt trong Ubuntu.
- name : có thể định nghĩa ở đây một danh sách các package cần cài đặt. Ở đây, danh sách này được định nghĩa riêng trong một biến có tên "packages" trong mục "vars" để cho tác vụ này rõ ràng hơn.

- state: được gán giá trị "present" nghĩa là ansible sẽ cài các gói này nếu chúng chưa được cài, còn nếu chúng đã có rồi thì bỏ qua không thực hiện việc cài chúng nữa. Nói ngắn gọn là đảm bảo sự hiện diện của chúng. Ngoài ra ta có thể gán các giá trị "absent"(đảm bảo chúng không hiện diện), "latest" (đảm bảo chúng hiện diện và có phiên bản mới nhất), "build-deps"(đảm bảo những gói mà chúng phụ thuộc vào cũng hiện diện), hoặc "fixed" (gắng sửa lại hệ thống nếu có những phụ thuộc bị thiếu).


* Một cách dễ hiểu, tập tin playbook java11-setup.yml ở trên tương đương với việc thực hiện các lệnh sau để cài đặt java 11 :

sudo add-apt-repository ppa:openjdk-r/ppa
sudo apt install openjdk-11-jdk
sudo apt install openjdk-11-jre

7. Tạo một tập tin Inventory cho Ansible

Như đã đề cập trong mục (3) ở trên về cách hoạt động của Ansible. Ta vừa định nghĩa các tác vụ để Ansible thực thi. Giờ ta phải cung cấp danh sách các host để Ansible tiến hành thực hiện các tác vụ này trên đó. Ở đây ta tạo một tập tin Inventory để cung cấp danh sách các host này. Thông tin cụ thể về Inventory có thể tham khảo tại đây https://docs.ansible.com/ansible/latest/user_guide/intro_inventory.html

Ta đặt tên tập tin Inventory này là inventory-all-vms.yml và nó có nội dung như sau :

all:
children:
ubuntu_servers:
hosts:
jenkins_ubuntu18:
ansible_host: jenkins.local

toan_local:
hosts:
toan_ubuntu16:
ansible_host: toan.local

Trong tập tin trên, ta khai báo hai hosts là jenkins.local và toan.local vì đây là hai VM mà tôi dùng Vagrant để tạo ra. Ngoài ra bạn cũng có thể dùng adresse ip để định nghĩa cho các host này.

Đến đây ta đã có tập tin playbook và inventory, từ control node của ansible ta có thể dùng lệnh ansible-playbook để thực hiện việc cài đặt java 11 (định nghĩa trong playbook) cho các hosts (định nghĩa trong inventory) theo cú pháp sau :

ansible-playbook java11-setup.yml -i inventory-all-vms.yml

 

8. Dùng Vagrant tạo control node và hosts cho Ansible và cấu hình cho chúng

Dưới đây, ta sẽ dùng Vagrant để tạo một máy ảo làm control node và hai máy ảo làm host cho ansible. Xem chi tiết việc dùng Vagrant để tạo VM tại đây https://openspacevn.blogspot.com/2020/11/cai-at-vagrant-tren-windows.html

Tập tin Vagrantfile định nghĩa ba máy ảo này có nội dung như sau :

Vagrant.configure("2") do |config|

#common part of vms
BOX_IMAGE = "ubuntu/bionic64" # bionic 64 = ubuntu 18.04 64 bits

#ansible vm description
config.vm.define "ansible" do |ansible|
ansible.vm.box = BOX_IMAGE
ansible.vm.hostname = "ansible"
ansible.vm.network "private_network", ip: "10.0.0.10", virtualbox__intnet: true
ansible.vm.provision "shell", inline: "apt install python -yq", privileged: true
ansible.vm.provision "shell", inline: "sudo apt-get install -yq software-properties-common", privileged: true
ansible.vm.provision "shell", inline: "sudo apt-add-repository -y ppa:ansible/ansible", privileged: true
ansible.vm.provision "shell", inline: "sudo apt-get update -yq", privileged: true
ansible.vm.provision "shell", inline: "sudo apt-get install -yq ansible", privileged: true
ansible.vm.provision "shell", inline: "sudo apt-get install -yq mc", privileged: true
end

#jenkins vm description
config.vm.define "jenkins" do |jenkins|
jenkins.vm.box = BOX_IMAGE
jenkins.vm.hostname = "jenkins"
jenkins.vm.network "private_network", ip: "10.0.0.11", virtualbox__intnet: true
jenkins.vm.provision "shell", inline: "sudo apt-get install -yq mc", privileged: true
end

config.vm.define "toan" do |toan|
toan.vm.box = "ubuntu/xenial64"
toan.vm.hostname = "toan"
toan.vm.network "private_network", ip: "10.0.0.12", virtualbox__intnet: true
toan.vm.provision "shell", inline: "sudo apt-get install -yq mc", privileged: true
end

end

Như ta thấy trong tập tin trên, máy ảo control node có tên "ansible" và trên đó ta sẽ cài đặt Python và Ansible. Hai máy ảo host có tên là "jenkins" và "toan"

* Cấu hình để control node có thể kết nối với các host thông qua SSH

Ta mở màn hình lệnh tại thư mục chứa tập tin Vagrantfile, chẳng hạn tập tin này được lưu tại thư mục C:\vagrant\ubuntu

Tại commande line ở thư mục này, ta đánh lệnh : "vagrant up ansible" để khởi động control node tên là ansible

C:\vagrant\ubuntu>vagrant up ansible


Sau khi máy ảo ansible này khởi động, ta kết nối vào nó bằng lệnh "vagrant ssh ansible"

C:\vagrant\ubuntu>vagrant ssh ansible

Tương tự ta cũng khởi động và kết nối vào máy ảo "toan" như sau

C:\vagrant\ubuntu>vagrant up toan
C:\vagrant\ubuntu>vagrant ssh toan

 a) Cấu hình các hosts

Tại máy ảo "toan" vừa kết nối đến này, ta sẽ cấu hình để cho control node "ansible" có thể kết nối ssh đến nó như sau.

Trước tiên ta mở tập tin cấu hình ssh /etc/ssh/sshd_config

vagrant@toan:~$ sudo vi /etc/ssh/sshd_config

Rồi kiểm tra các dòng thông tin sau nếu chưa được kích hoạt (tức có dấu # ở đầu dòng hoặc có giá trị là "no") thì ta kích hoạt nó bằng cách xóa dấu # ở đầu dòng hoặc đổi giá trị thành "yes" :

PubkeyAuthentication yes
AuthorizedKeysFile <thông tin đường dẫn>
PasswordAuthentication yes

Sau đó ta khởi động lại service sshd để cập nhật cấu hình vừa thay đổi với lệnh "sudo service sshd restart" :

vagrant@toan:~$ sudo service sshd restart

Với máy ảo "jenkins", ta cũng khởi động và cấu hình tương tự như máy ảo "toan":

C:\vagrant\ubuntu>vagrant up jenkins
C:\vagrant\ubuntu>vagrant ssh jenkins
vagrant@jenkins:~$ sudo vi /etc/ssh/sshd_config
vagrant@jenkins:~$ sudo service sshd restart

b) cấu hình cho control node "ansible"

Trên máy ảo "ansible" ta kiểm tra xem máy đã có public key rsa hay chưa :

vagrant@ansible:~$ ls -l ~/.ssh/
total 4
-rw------- 1 vagrant vagrant 389 Dec 21 09:07 authorized_keys

Trong trường hợp này ta thấy chưa có, ta sẽ phát sinh public key cho máy ảo "ansible" với lệnh ssh-keygen :

vagrant@ansible:~$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/vagrant/.ssh/id_rsa): <nhấn enter để mặc định phát sinh các tập tin này ở thư mục .ssh>
Enter passphrase (empty for no passphrase): <nhấn enter>
Enter same passphrase again: <nhấn enter>
Your identification has been saved in /home/vagrant/.ssh/id_rsa.
Your public key has been saved in /home/vagrant/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:XijkRt3uI++yKn06gMC+n6kvpAUHM5eOs5r8HT1RkBs vagrant@ansible
The key's randomart image is:
+---[RSA 2048]----+
|   .   ..        |
|+ o    E..       |
|.B    o +..      |
|=.o  + ..o       |
|.* .  +.S o      |
|.oo ...o.o       |
|=o.  + oo o      |
|++  = + +o .     |
| .** oo=.+o      |
+----[SHA256]-----+

Giờ đây public và private key rsa đã được phát sinh :

vagrant@ansible:~$ ls -l ~/.ssh/
total 12
-rw------- 1 vagrant vagrant 389 Dec 21 09:07 authorized_keys
-rw------- 1 vagrant vagrant 1675 Dec 21 09:57 id_rsa
-rw-r--r-- 1 vagrant vagrant 397 Dec 21 09:57 id_rsa.pub

Đến đây ta sao chép public key của máy ảo "ansible" đến các host để cho phép nó kết nối với các máy này thông qua ssh với lệnh ssh-copy-id như sau :

vagrant@ansible:~$ sudo ssh-copy-id vagrant@toan.local
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/home/vagrant/.ssh/id_rsa.pub"
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed

/usr/bin/ssh-copy-id: ERROR: ssh: Could not resolve hostname toan.local: Temporary failure in name resolution

Nếu bị lỗi khi kết nối ssh với hostname "toan.local" như trên ta có thế thay thế hostname bằng địa chỉ ip "10.0.0.12". Trong tập tin Vagrantfile địa chỉ ip ứng với hostname "toan" là "10.0.0.12"

vagrant@ansible:~$ sudo ssh-copy-id vagrant@10.0.0.12
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/home/vagrant/.ssh/id_rsa.pub"
The authenticity of host '10.0.0.12 (10.0.0.12)' can't be established.
ECDSA key fingerprint is SHA256:65N5OhnmyUuoJ0F7qIOa33eA0OGci4CjP1C/aePIlvw.
Are you sure you want to continue connecting (yes/no)? yes
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
vagrant@10.0.0.12's password: <password là vagrant>

Number of key(s) added: 1

Now try logging into the machine, with: "ssh 'vagrant@10.0.0.12'"
and check to make sure that only the key(s) you wanted were added.

Để kiểm tra việc thêm public key thành công, ta kết nối đến host, rồi thoát ra bằng lệnh exit :

vagrant@ansible:~$ ssh vagrant@10.0.0.12
vagrant@toan:~$ exit

Tương tự, ta cũng sao chép public key của máy ảo "ansible" vào máy ảo "jenkins" như trên :

vagrant@ansible:~$ sudo ssh-copy-id vagrant@jenkins.local

* Dùng ansible để cài đặt java 11

Đến đây, ta đã tạo được một mạng lưới gồm control node "ansible" và hai host "toan" và "jenkins" và cấu hình để vm "ansible" có thể kết nối ssh với hai host này. Vậy là từ vm "ansible" ta có thể dùng hai tập tin java11-setup.yml và inventory-all-vms.yml định nghĩa ở trên để cài đặt java 11 lên hai vm "toan" và "jenkins".

Trong thư mục C:\vagrant\ubuntu (tức thư mục chứa tập tin Vagrantfile), ta tạo thư mục "toan" và chép hai tập tin java11-setup.yml và inventory-all-vms.yml vào đây

Từ vm "ansible", ta có thể truy xuất đến hai tập tin này tại /vagrant/toan

Chú ý, nếu ta bị lỗi không kết nối được đến host bằng hostname như ở trên, thì ta phải thay đổi hostname bằng địa chỉ ip trong tập tin inventory-all-vms.yml như sau :

all:
children:
ubuntu_servers:
hosts:
jenkins_ubuntu18:
ansible_host: 10.0.0.11

toan_local:
hosts:
toan_ubuntu16:
ansible_host: 10.0.0.12

Chẳng hạn nếu ta chỉ muốn cài java 11 trên host "toan" thôi chứ không phải trên tất cả các host, thì trong tập tin java11-setup.yml, ta định nghĩa host là toan_ubuntu16 :

- hosts: toan_ubuntu16

Sau đó dùng lệnh ansible-playbook để thực thi :

vagrant@ansible:~$ ansible-playbook /vagrant/toan/java11-setup.yml -i /vagrant/toan/inventory-all-vms.yml

PLAY [toan_ubuntu16] ***************************************************************************************************

TASK [Gathering Facts] *************************************************************************************************
ok: [toan_ubuntu16]

TASK [add openjdk repository] ******************************************************************************************
changed: [toan_ubuntu16]

TASK [install openjdk 11] **********************************************************************************************
changed: [toan_ubuntu16]

PLAY RECAP *************************************************************************************************************
toan_ubuntu16 : ok=3 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

Ta thấy java 11 được cài đặt trên host toan_ubuntu16.

Nếu muốn thực hiện cài đặt java 11 trên tất cả các host thì ta định nghĩa host là all trong tập tin java11-setup.yml

- hosts: all

Thực hiện lại lệnh ansible-playbook :

vagrant@ansible:~$ ansible-playbook /vagrant/toan/java11-setup.yml -i /vagrant/toan/inventory-all-vms.yml

PLAY [all] *************************************************************************************************************

TASK [Gathering Facts] *************************************************************************************************
ok: [jenkins_ubuntu18]
ok: [toan_ubuntu16]

TASK [add openjdk repository] ******************************************************************************************
ok: [toan_ubuntu16]
changed: [jenkins_ubuntu18]

TASK [install openjdk 11] **********************************************************************************************
ok: [toan_ubuntu16]
changed: [jenkins_ubuntu18]

PLAY RECAP *************************************************************************************************************
jenkins_ubuntu18 : ok=3 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
toan_ubuntu16 : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

Ta thấy java 11 được cài đặt trên cả hai host toan_ubuntu16 và jenkins_ubuntu18.


Thứ Sáu, 27 tháng 11, 2020

Cài đặt Vagrant trên Windows

Vagrant là một công cụ cho phép triển khai (deploy) các máy ảo (virtual machine) một cách nhanh chóng và tự động. Chẳng hạn bạn phát triển một ứng dụng Java trên Windows và muốn kiểm tra ứng dụng này có chạy tốt trên Linux hay không, Vagrant sẽ giúp bạn thực hiện điều này. Nó giúp bạn tạo ra một môi trường (environment) để kiểm tra (test) và phát triển phần mềm (developement).

Mục đích của Vagrant là cho phép triển khai và cấu hình (configure) các máy ảo một cách tự động từ các boxes.

Muốn dùng Vagrant thì trước hết cần phải cài đặt trước một phần mềm máy ảo (chẳng hạn VirtualBox hay VMware)

 

Một số thuật ngữ

- Vagrant Box: được xem là ảnh (image) hay bản mẫu (template) mà ta sẽ sử dụng để triển khai các máy ảo của chúng ta. Bạn có thể tìm các box tại đây https://app.vagrantup.com/boxes/search

- Packer : là công cụ cho phép bạn tạo các ảnh, xem tại đây https://learn.hashicorp.com/tutorials/packer/getting-started-build-image

- Vagrantfile : là tập tin cấu hình mà Vagrant dùng để triển khai và cấu hình các máy ảo

- Provider : là phần mềm máy ảo cho phép Vagrant triển khai các máy ảo trên đó. Như VirtualBox, VMware, Hyper-V, Docker

- Provisioner : Một khi máy ảo được triển khai, Provisionner sẽ khởi động tiến trình cài đặt và cấu hình tự động cho các máy ảo bằng : Script Shell, Ansible... 

 

Cài đặt VirtualBox

Ở đây ta sẽ dùng VirtualBox là phần mềm cho phép cài đặt máy ảo trên Windows. VirtualBox là phần mềm open source miễn phí, bạn có thể tải nó về tại đây https://www.virtualbox.org/wiki/Downloads

Chú ý là Provider phải cài đặt trước khi sử dụng Vagrant.


Cài đặt Vagrant

Cài đặt Vagrant khá đơn giản, bạn tải phiên bản của nó ứng với hệ điều hành của máy bạn về tại địa chỉ này https://www.vagrantup.com/downloads.html để cài đặt.

Sau khi việc cài đặt hoàn tất, trong commande line trên Windows bạn có thể đánh lệnh sau để kiểm tra version của Vagrant vừa cài đặt :

vagrant version

Sẽ hiển thị kết quả :
Installed Version: 2.2.14
Latest Version: 2.2.14

You're running an up-to-date version of Vagrant!
Như vậy là bạn đã cài đặt xong Vagrant, tiếp theo ta sẽ xem sử dụng Vagrant như thế nào.


Sử dụng Vagrant trong Windows

Trước tiên, ta tạo một thư mục cho dự án, chẳng hạn C:\vagrant\ubuntu_bionic64 rồi ta mở command line từ thư mục này (shift+ nhấp chuột phải rồi chọn command line)

Danh sách các images của ubuntu cho Vagrant tại đây https://app.vagrantup.com/ubuntu
Chẳng hạn ta muốn dùng một máy ảo Ubuntu 18.04, đánh dòng lệnh sau đây :

vagrant init ubuntu/bionic64

Lệnh này sẽ tự động tạo ra tập tin Vagrantfile trong thư mục hiện hành, chính là trong tập tin này mà ta sẽ định nghĩa những thứ ta muốn tự động hóa. Hiện tại, tập tin này có nội dung sau :

Vagrant.configure("2") do |config|
  config.vm.box = "ubuntu/bionic64"
end

Tiếp theo, ta đánh lệnh :
vagrant up


Vì đây là lần đầu tiên ta dùng Vagrant nên nó sẽ tải box định nghĩa trong Vagrantfile về rồi sau đó máy ảo Vagrant này sẽ được cài đặt và khởi động .

Đôi khi ta gặp lỗi sau :

Error :
The box 'ubuntu/bionic64' could not be found or
could not be accessed in the remote catalog. If this is a private
box on HashiCorp's Vagrant Cloud, please verify you're logged in via
`vagrant login`. Also, please double-check the name. The expanded
URL and error message are shown below:

URL: ["https://vagrantcloud.com/ubuntu/bionic64"]
Error: SSL certificate problem: self signed certificate in certificate chain

Nếu gặp lỗi SSL như trên, ta có thể thêm box bằng cách dùng option --insecure như sau :
vagrant box add --insecure ubuntu/bionic64 
Rồi gõ lại lệnh vagrant up. Một khi máy ảo này khởi động thành công không lỗi, có thể kết nối vào nó với lệnh :
vagrant ssh

Để dừng máy ảo, gõ lệnh :

vagrant halt

Để xóa một máy ảo Vagrant, gõ lệnh :
vagrant destroy