Monday

4 May, 2020

Azure Dynamic Inventory with Ansible 小記

Azure Dynamic Inventory with Ansible 小記

上次寫 Azure Dynamic Inventory 是 2018/2 的事情了 :)

在 Azure 的官方文件上說明, 如果 Ansible 版本 >= 2.8 , Dynamic Inventory 使用 plug-in 方式, 而不是使用之前的 azure_rm.py


今天就是來實驗 azure_rm – Azure Resource Manager inventory plugin

OS: container with openSUSE Leap 15.1

Ansible: 2.9.7

先來看看  Ansible 官方上面的說明

以及剛剛看到的微軟官方說明文件

不過在這之前先寫個小插曲
就是剛好又遇到 client secret keys are expired, 所以先寫一下, 更換認證檔案的部分

參考之前的文章

認證的資訊是透過 az ad sp create-for-rbac 指令來建立的

但是現在舊的認證資訊過期了, 想要先找出來

Azure 認證檔案的內容, 如下

~/.azure/credentials

[default]
subscription_id=6a2bdf3b-XXXX-XXXX-XXXX-3371d3401feb
client_id=d06f8905-XXXX-XXXX-XXXX-3e0bcf22a853
secret=b7f0df5b-XXXX-XXXX-XXXX-8aaca284f706
tenant=4cd326d7-XXXX-XXXX-XXXX-df56dc9dabd4


如何找出舊的認證呢? 下面的指令可以列出所有的資訊
>  az  ad  sp  list  --output  table

但是我們要過濾出我們建立的

# az  ad  sp list --output table | grep azure-cli

True              azure-cli-2018-02-14-06-03-46                                d06f8905-ad21-425b-9da5-3e0bcf22a853  False                        azure-cli-2018-02-14-06-03-46                                0c2d3a46-847a-4292-a9ad-8b72baf02fb7  ServicePrincipal  Microsoft.DirectoryServices.ServicePrincipal  Application                                  4cd336d7-b5ad-40a7-83cc-df57dc9dabd4  sakana              http://azure-cli-2018-02-14-06-03-46

  • 我的做法是過濾 azure-cli 關鍵字
  • 從輸出的 azure-cli-201x-xx-xx-xx-xx-xx 就可以知道建立的時間
  • 比對輸出的第三欄位 AppId~/.azure/credentials 內的 client_id 就可以知道是那一個了

刪除舊的認證

# az  ad  sp delete --id d06f8905-ad21-425b-9da5-3e0bcf22a853

Removing role assignments

  • --id 後面接 AppId

接下來建立新的認證資訊

# az  ad  sp  create-for-rbac --query  '{"client_id": appId, "secret": password, "tenant": tenant}'

Retrying role assignment creation: 1/36
{
  "client_id": "d06f8905-XXXX-XXXX-XXXX-3e0bcf22a853",
  "secret": "b7f0df5b-XXXX-XXXX-XXXX-8aaca284f706",
  "tenant": "4cd326d7-XXXX-XXXX-XXXX-df56dc9dabd4"
}

接下來還要有 subscription_id
使用 az account 指令取得

$ az  account  show  --query  "{ subscription_id: id }"
{
 "subscription_id": "6a2bdf3b-XXXX-XXXX-XXXX-3371d3401feb"
}

修改 ~/.azure/credentials , 主要是修改 client_id 與 secret

#vi  ~/.azure/credentials

[default]
subscription_id=6a2bdf3b-XXXX-XXXX-XXXX-3371d3401feb
client_id=新的_client_id
secret=新的_secret
tenant=4cd326d7-XXXX-XXXX-XXXX-df56dc9dabd4

解決完認證問題之後就可以來進行小測試

首先用微軟官方的測試方式

建立一個 myazure_rm.yml  檔案
內容如下:

# vi  myazure_rm.yml

plugin: azure_rm
include_vm_resource_groups:
- sakanastudy
auth_source: auto

keyed_groups:
- prefix: tag
  key: tags

  • sakanastudy 請換成自己的 Resource Group 名稱

# ansible  all  -m ping -i  ./myazure_rm.yml  -u  YOUR_USER  --ask-pass

SSH password: 
test01_b7be | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3.6"
    },
    "changed": false,
    "ping": "pong"
}

  • 這邊可以觀察到 有抓到 resource group 內的機器 test01
  • 我的測試機不是用 key, 是用 password 方式, 所以我指定 -u 使用者, 以及 --ask-pass 來輸入密碼, 如果要這樣的方式, 機器要裝 sshpass 套件, 所以下次要來更新容器版本 :)

如果要更進一步
建議叄考官方的文件內容


這樣也算是又前進一步

~enjoy it



Reference:



Friday

1 May, 2020

三大雲平台工具容器升級小記 - 使用 AWS CLI v2 with openSUSE Leap 15.1 Container

三大雲平台工具容器升級小記 - 使用 AWS CLI v2  with openSUSE Leap 15.1 Container

OS: container with openSUSE Leap 15.1

上次升級是 2020/1/5 , 這次會來升級的原因是 

先整理結果

升級前
OS: openSUSE Leap 15.1
awscli:  aws-cli/1.16.310 Python/3.6.9
gcloud: Google Cloud SDK 274.0.1
azure-cli: 2.0.78

升級後
OS: openSUSE Leap 15.1
awscli:  aws-cli/2.0.10 Python/3.7.3
gcloud: Google Cloud SDK 290.0.1
azure-cli: 2.5.1

AWS CLI v2 安裝文件

GCP Cloud SDK 版本



這次的做法還是會透過 docker build 指令來進行
  • 我有比較過 docker build 以及使用現有的 docker image 修改後再使用 docker commit 建立的 image 大小還是很有差異的

Dockerfile 的部分我是拿之前 openSUSE Leap 15.1 來修改

修改細節
  • Update time
  • 加入 LANG C.UTF-8
  • 不需下載 azure_rm.py , 因為現在是用 plug-in 方式
  • 安裝 unzip 與  AWS CLI v2 
  • Google SDK 版本還有下載的檔案路徑以及檔案名稱


列出 diff 的結果給大家參考


> diff opensuseLeap151_ansible_20200501_Dockerfile opensuseLeap151_ansible_20200105_Dockerfile 

6c6
< # update: 20200501
---
> # update: 20200105
9,12c9
< # Set LANG for UTF-8 - for Chinese
< ENV LANG C.UTF-8
< # Install python3-pip, upgrade pip, ansible[azure]
---
> # Install python2-pip, upgrade pip, ansible[azure]
22,28c19,22
< RUN zypper install -y wget
< # azure_rm.py no need to download 
< # Starting with Ansible 2.8, Ansible provides an Azure dynamic-inventory plug-in
< # https://docs.ansible.com/ansible/latest/plugins/inventory/azure_rm.html
< # old azure_rm.py URL https://raw.githubusercontent.com/ansible/ansible/devel/contrib/inventory/azure_rm.py
< # 
---
> RUN zypper install -y wget && \
>   wget  https://raw.githubusercontent.com/ansible/ansible/devel/contrib/inventory/azure_rm.py && \
>   chmod a+x azure_rm.py && \
>   mv azure_rm.py /root
40d33
< #### Azure #### 
47,48c40,41
< #install vim tar gzip jq unzip
< RUN zypper install -y vim tar gzip jq unzip
---
> #install vim tar gzip jq
> RUN zypper install -y vim tar gzip jq
51,60c44,47
< #### AWS ####
< # Install awscli v1
< #RUN pip3 install awscli
< #RUN echo "source /usr/bin/aws_bash_completer" >> /root/.bashrc
< # Install awscli v2
< RUN curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" && \
<   unzip awscliv2.zip && \
<   /aws/install
< RUN echo "complete -C '/usr/local/bin/aws_completer' aws" >> /root/.bashrc
---
> # Install awscli
> RUN pip3 install awscli
> RUN echo "source /usr/bin/aws_bash_completer" >> /root/.bashrc
62,63c49
< #### GCP ####
< # Install google cloud SDK 290.0.1
---
> # Install google cloud SDK 274.0.1
65,66c51,52
< RUN wget https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/google-cloud-sdk-290.0.1-linux-x86_64.tar.gz && \
<   tar zxvf google-cloud-sdk-290.0.1-linux-x86_64.tar.gz && \
---
> RUN wget https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/google-cloud-sdk-274.0.1-linux-x86_64.tar.gz && \
>   tar zxvf google-cloud-sdk-274.0.1-linux-x86_64.tar.gz && \






Dockerfile 內容如下

# openSUSE Leap 15.1 with ansible, azure-cli
FROM opensuse/leap:15.1

# Author
# MAINTAINER 已經棄用, 之後要使用 LABEL 方式
# update: 20200501
LABEL maintainer="sakana@cycu.org.tw"

# Set LANG for UTF-8 - for Chinese
ENV LANG C.UTF-8

# Install python3-pip, upgrade pip, ansible[azure]
RUN zypper install -y python3-pip && \
  pip3 install --upgrade pip && \
  pip3 install ansible[azure]

# Install openssh, set ls alias
RUN zypper install -y openssh
RUN echo "alias ls='ls --color=tty'" >> /root/.bashrc

# Install wget, download azure_rm.py, set permission
RUN zypper install -y wget

# azure_rm.py no need to download 
# Starting with Ansible 2.8, Ansible provides an Azure dynamic-inventory plug-in
# https://docs.ansible.com/ansible/latest/plugins/inventory/azure_rm.html
# old azure_rm.py URL https://raw.githubusercontent.com/ansible/ansible/devel/contrib/inventory/azure_rm.py

# Create working directory in /root
RUN mkdir /root/.azure && \
  mkdir /root/.aws && \
  mkdir /root/playbook && \
  mkdir -p /root/.config/gcloud && \
  wget https://raw.githubusercontent.com/sakanamax/LearnAnsible/master/template/ansible.cfg && \
  mv /ansible.cfg /root && \
  wget https://raw.githubusercontent.com/sakanamax/LearnAnsible/master/template/hosts && \
  mv /hosts /root

#### Azure #### 
# Install azure-cli
RUN zypper install -y curl && \
  rpm --import https://packages.microsoft.com/keys/microsoft.asc && \
  zypper addrepo --name 'Azure CLI' --check https://packages.microsoft.com/yumrepos/azure-cli azure-cli && \
  zypper install --from azure-cli -y azure-cli

#install vim tar gzip jq unzip
RUN zypper install -y vim tar gzip jq unzip
RUN echo "set encoding=utf8" > /root/.vimrc

#### AWS ####
# Install awscli v1
#RUN pip3 install awscli
#RUN echo "source /usr/bin/aws_bash_completer" >> /root/.bashrc

# Install awscli v2
RUN curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" && \
  unzip awscliv2.zip && \
  /aws/install
RUN echo "complete -C '/usr/local/bin/aws_completer' aws" >> /root/.bashrc

#### GCP ####
# Install google cloud SDK 290.0.1
ENV CLOUDSDK_CORE_DISABLE_PROMPTS 1
RUN wget https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/google-cloud-sdk-290.0.1-linux-x86_64.tar.gz && \
  tar zxvf google-cloud-sdk-290.0.1-linux-x86_64.tar.gz && \
  /google-cloud-sdk/install.sh && \
  echo "if [ -f '/google-cloud-sdk/path.bash.inc' ]; then . '/google-cloud-sdk/path.bash.inc'; fi" >> /root/.bashrc && \
  echo "if [ -f '/google-cloud-sdk/completion.bash.inc' ]; then . '/google-cloud-sdk/completion.bash.inc'; fi" >> /root/.bashrc



使用 docker build 指令建立 image

> docker build  -t  sakana/ansible_opensuse151:20200501  -f  ./opensuseLeap151_ansible_20200501_Dockerfile   .

  • 使用 -f 指定 Dockerfile 名稱
  • 最後是 ” . “ 目前的目錄


測試 container image

> docker  run  -v  ~/.aws:/root/.aws  -v  ~/.azure:/root/.azure  -v ~/.config/gcloud:/root/.config/gcloud  -it  sakana/ansible_opensuse151:20200105  /bin/bash

測試結果 OK, 建立  tag

觀察資訊
> docker  images

REPOSITORY                   TAG                 IMAGE ID            CREATED              SIZE
sakana/ansible_opensuse151   20200501            c8899a7046f8        About a minute ago   1.32GB
sakana/ansible_opensuse151   latest              3d76040b20fb        6 weeks ago          1.19GB
opensuse/leap                15.1                fef5ad254f63        2 months ago         103MB

建立 tag 
> docker  tag  c8899a7046f8  sakana/ansible_opensuse151:latest

登入 docker
> docker  login

上傳 image
> docker  push  sakana/ansible_opensuse151:20200501

> docker  push  sakana/ansible_opensuse151:latest

完工, 以後使用就用

> docker  run  -v  ~/.aws:/root/.aws  -v  ~/.azure:/root/.azure  -v ~/.config/gcloud:/root/.config/gcloud  -it  sakana/ansible_opensuse151  /bin/bash


~ enjoy it

Reference:

exfat in openSUSE Leap 15.1 小記

exfat in openSUSE Leap 15.1 小記

最近想到我們家的 Nintendo Switch 只有拿來使用健身環大冒險運動, 其他的都沒啥在動, 馬力歐賽車與馬力歐派對大概就是過年才有機會用到 :)

所以就去研究了一下數位版的遊戲, 也湊團加入 Nintendo Switch Online Family Plan.

研究數位版遊戲的時候, 才突然發現, 之前給 Nintendo Switch 插的 SD Card 只有 16GB

所以就上網去找資料, 如何擴充卡片

首先是參考任天堂官網把新的 SD 卡格式化

然後看網路上的文章, 只要將 舊的卡片上的 Nintendo 目錄複製過去就可以了

這個時候我發現, 當我用 nautilus 要存取新的 SD 卡的時候
出現下面的錯誤訊息 ( unknown filesystem type ‘exfat’ )


找了網路上的文章, 說要安裝 fuse-exfat

使用 zypper 搜尋 exfat 關鍵字

# zypper  search  exfat

Loading repository data...
Reading installed packages...

S | Name        | Summary                         | Type   
--+-------------+---------------------------------------+--------
  | exfat-utils | Utilities for exFAT file system       | package
  | fuse-exfat  | Free exFAT file system implementation | package

這邊有看到兩個套件, 但是其實兩個之後都會安裝 :)
使用 zypper  進行安裝

# zypper  install  fuse-exfat

Loading repository data...
Reading installed packages...
Resolving package dependencies...

The following 2 NEW packages are going to be installed:
  exfat-utils fuse-exfat

The following 2 recommended packages were automatically selected:
  exfat-utils fuse-exfat

2 new packages to install.
Overall download size: 108.7 KiB. Already cached: 0 B. After the operation, additional 286.6 KiB will be used.
Continue? [y/n/v/...? shows all options] (y): y


安裝完成之後, 再次使用 nautilus 觀察

果然就可以進行操作


搞定, 收工

~ enjoy it


Reference:

Sunday

29 March, 2020

使用 gcloud 指令建立快照與從快照建立磁碟與 GCE 小記

使用 gcloud 指令建立快照與從快照建立磁碟與 GCE 小記

OS: Container with openSUSE Leap 15

工作上三個雲端平臺都會碰到, 所以就想要使用一些工具或是方式來節省時間
畢竟偷懶是工程師前進最大的動力 :p
上次寫這類文章的時候是 2019/11 的時候, 時間過的真是快 : )

有的時候遇到業務需求, 要建立快照來複製 GCP 上面的機器進行實驗或是擴充

以下是一些自己在 GCP 上面的小記

建立快照
基本上就是使用 gcloud compute disks snapshot 的方式來建立

把他寫成 shell script

檔案 gcp_create_Disksnapshot.sh
內容如下:

#!/bin/bash

# edit by sakana 2020/3/28
# 建立 快照

# 顯示快照名稱輸入方式

echo ""
echo "請輸入快照名稱, 請用小寫英文或是-"
echo " 例如: test-20200328"
echo ""

# 設定 快照名稱
read -e -p "Please enter snapshot name: " -i "test-20200328" snapshot_name

# 設定 來源磁碟
echo "請輸入來源磁碟名稱"
read -e -p "Please enter source disk name: " -i "test20200328" source_disk_name
echo ""

# 設定 快照儲存位置
echo "請輸入快照儲存位置"
read -e -p "Please enter storage location : " -i "asia-east1" storage_location
echo ""

# 設定 來源磁碟所在的 zone
echo "輸入來源磁碟所在的 zone"
read -e -p "Please enter zone name: " -i "asia-east1-b" zone_name
echo ""

# 設定使用專案
read -e -p "Please enter project name: " -i "sakanatest" project_name

# 開始建立 快照
gcloud  compute disks snapshot $source_disk_name  --zone  $zone_name --storage-location $storage_location --snapshot-names $snapshot_name --project $project_name

# 列出排程
echo ""
echo "List snapshot  with project $project_name"
echo ""
gcloud compute snapshots list --project $project_name

從快照建立磁碟
使用 gcloud compute disk create 指令

把他寫成 shell script

檔案 gcp_create_Disk_from_snapshot.sh
內容如下:

#!/bin/bash

# edit by sakana 2020/3/28
# 從 快照 建立磁碟

echo ""
echo "這個 script 會從快照建立磁碟"
echo ""

# 設定使用專案
read -e -p "Please enter project name: " -i "sakanatest" project_name

# 列出專案目前的 snapshot
echo ""
echo "如果已經知道快照名稱, 可以不列出快照 list"
read -e -p "是否要列出專案 $project_name 的所有快照? (要列出所有快照請輸入小寫 yes) : " -i "no" list_snapshots
echo ""
[ $list_snapshots == yes ] && gcloud compute snapshots list --project $project_name
echo ""


# 設定 來源快照名稱
echo ""
echo "請輸入來源快照名稱"
read -e -p "Please enter source snapshot name: " -i "test-20200328" source_snapshot_name
echo ""

# 顯示快照資訊
echo "顯示該來源快照資訊, 請注意磁碟大小 (diskSizeGb): "
echo "========"
gcloud compute snapshots describe $source_snapshot_name
echo "========"

# 設定 磁碟名稱
echo ""
echo "請輸入要建立磁碟名稱"
read -e -p "Please enter new disk name: " -i "test20200328-2" new_disk_name
echo ""

# 設定 磁碟大小
echo "請輸入磁碟大小, 沒有指定單位的話, 預設是 GB"
read -e -p "Please enter disk size: " -i "10" new_disk_size

# 設定 磁碟所在的 zone
echo "輸入磁碟所在的 zone"
read -e -p "Please enter zone name: " -i "asia-east1-b" zone_name
echo ""

# 設定磁碟類型
echo ""
echo "請輸入磁碟的類型, pd-standard 標準磁碟 / pd-ssd SSD, 依據 Region 會有不同"
read -e -p "Please enter disk type: " -i "pd-standard" new_disk_type


# 開始建立 磁碟
gcloud  compute disks create $new_disk_name  --size $new_disk_size --zone  $zone_name --source-snapshot $source_snapshot_name --type $new_disk_type --project $project_name



最後一個步驟就是

從快照磁碟建立 GCE, 我這邊還有指定自訂的規格, 網路與 Subnet

使用 gcloud compute insances create 指令

把他寫成 shell script

檔案 gcp_create_CustomSpec_CustomNetwork_from_snapshot_gce.sh
內容如下:

#!/bin/bash

# edit by sakana 2020/3/28
# 建立 從快照磁碟建立客製化GCE 指定 Subnet
# 從快照建立執行個體的行爲, 其實是兩個動作. 1-由快照建立磁碟, 2-由快照磁碟建立執行個體
# 這個 script 有用到 gcloud topic escaping ( https://cloud.google.com/sdk/gcloud/reference/topic/escaping )
# 就是如果一個 argument 會用到多個逗號 ( , ) , 要使用跳脫字元來代替逗號
# 語法 在兩個 ^ 內定義要定義的替代字元, 例如使用冒號來代替逗號
# 範例  --address ^:^123.456.789.198:22.333.146.189 就等於 123.456.789.198,22.333.146.189

echo ""
echo "從快照磁碟建立客製化的 GCE, 網路指定 Subnet"
echo "CPU / 記憶體只能用整數, subnet 名稱請先準備好"
echo ""


# 設定使用專案
read -e -p "Please enter project name: " -i "sakanatest" project_name

# 列出專案目前的 磁碟
echo ""
echo "如果已經知道快照磁碟名稱, 可以不列出快照磁碟 list"
read -e -p "是否要列出專案 $project_name 的所有磁碟? (要列出所有快照請輸入小寫 yes) : " -i "no" list_disks
echo ""
[ $list_disks == yes ] && gcloud compute disks list --project $project_name
echo ""

# 設定 VM 名稱
echo "輸入 VM 名稱"
read -e -p "Please enter vm name: " -i "test" gce_name
echo ""

# 設定 zone
read -e -p "Please enter zone name: " -i "asia-east1-b" zone_name

# 設定 cpu 數量
read -e -p "Please enter cpu number: " -i "1" cpu_number

# 設定 記憶體大小
read -e -p "Only use integer, Please enter memory GB: " -i "4" mem_size

# 設定 Subnet 名稱
read -e -p "Please enter Subnet name: " -i "sakana-test-10-12-53" subnet_name

# 設定快照磁碟
echo ""
echo "輸入快照磁碟名稱"
read -e -p "Please enter disk name: " -i "test20200328-2" disk_name
echo ""

# 開始建立 GCE, --custom-extensions 爲擴充記憶體
gcloud beta compute instances create $gce_name --zone $zone_name --custom-extensions --custom-cpu $cpu_number --custom-memory $mem_size  --subnet $subnet_name --disk ^:^name=$disk_name:device-name=$disk_name:mode=rw:boot=yes:auto-delete=yes  --project $project_name


慢慢地把工作中的需求整理成 script
往 GCP 更進一步

~ enjoy it

Reference

Sunday

22 March, 2020

AWS Client VPN with openSUSE leap 15.1 小記

AWS Client VPN with openSUSE leap 15.1 小記

OS: container with openSUSE Leap 15.1

OS: openSUSE Leap 15.1

之前就有看到 AWS Client VPN 的文章, 但是沒有時間來進行 Lab

想法: 
  • 透過 AWS Client VPN 可以使用桌機或是筆電接入 AWS VPN 的內網, 達成在本機使用 Ansible 進行 AWS 上面的資源調整或是佈署. 
  • 因為不是所有的resource 都有 public IP, 另外也不一定要想要弄台跳板機, 或是把 playbook 放在上面


使用 container 來建立相關步驟的原因
  • 確保有相關 cli 環境, 例如 aws cli / gcloud / az
  • 建立過程中如果有本機不需要的套件需要安裝, 不會影響到本機
  • 也可以用本機來進行建立過程


==== 在主機上面 ====

啟動 container

> docker  run  -v  ~/.aws:/root/.aws -v  ~/.azure:/root/.azure  -v ~/.config/gcloud:/root/.config/gcloud  -v  ~/.ssh:/root/.ssh  -it  sakana/ansible_opensuse151  /bin/bash

  • 這邊也可以考慮掛載一個臨時目錄等等將相關檔案匯出
    • -v /home/sakana/下載/test20200321:/root/test20200321

==== 在 container 內 ====

參考官方文件


產生伺服器和用戶端憑證及金鑰

因為容器裡面沒有裝 git 所以就先安裝 git

#zypper  install  -y  git

將 easy-rsa clone 下來

# git  clone  https://github.com/OpenVPN/easy-rsa.git

進入 easy-rsa 目錄

# cd   easy-rsa/easyrsa3

初始化新的 PKI 環境

# ./easyrsa  init-pki

init-pki complete; you may now create a CA or requests.
Your newly created PKI dir is: /root/easy-rsa/easyrsa3/pki

建置新的憑證授權機構 (CA)
# ./easyrsa  build-ca  nopass

Using SSL: openssl OpenSSL 1.1.0i-fips  14 Aug 2018
Generating RSA private key, 2048 bit long modulus
........................................................................................+++++
..............................................+++++
e is 65537 (0x010001)
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Common Name (eg: your user, host, or server name) [Easy-RSA CA]:  可以輸入自訂名稱

CA creation complete and you may now import and sign cert requests.
Your new CA certificate file for publishing is at:
/root/easy-rsa/easyrsa3/pki/ca.crt

產生伺服器憑證和金鑰
# ./easyrsa  build-server-full  server  nopass

Using SSL: openssl OpenSSL 1.1.0i-fips  14 Aug 2018
Generating a 2048 bit RSA private key
.......................................................................+++++
.....+++++
writing new private key to '/root/easy-rsa/easyrsa3/pki/easy-rsa-237.niuWFO/tmp.z1xt2p'
-----
Using configuration from /root/easy-rsa/easyrsa3/pki/easy-rsa-237.niuWFO/tmp.7dpbOC
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
commonName            :ASN.1 12:'server'
Certificate is to be certified until Jun 21 13:11:46 2022 GMT (825 days)

Write out database with 1 new entries
Data Base Updated


產生用戶端憑證和金鑰

# ./easyrsa  build-client-full  client1.domain.tld  nopass

Using SSL: openssl OpenSSL 1.1.0i-fips  14 Aug 2018
Generating a 2048 bit RSA private key
.........................................................+++++
............................+++++
writing new private key to '/root/easy-rsa/easyrsa3/pki/easy-rsa-164.uQNueZ/tmp.oBHVMB'
-----
Using configuration from /root/easy-rsa/easyrsa3/pki/easy-rsa-164.uQNueZ/tmp.aWJmw3
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
commonName            :ASN.1 12:'client1.domain.tld'
Certificate is to be certified until Jun 21 13:07:36 2022 GMT (825 days)

Write out database with 1 new entries
Data Base Updated

  • 務必儲存用戶端憑證和用戶端私有金鑰,因為您在設定用戶端時需要它們


將伺服器憑證和金鑰及用戶端憑證和金鑰複製到自訂資料夾,然後導覽到自訂資料夾
他的範例是 /custom_folder , 我是用自行掛載的資料夾

# cp  pki/ca.crt   /root/test20200321/

# cp  pki/issued/server.crt   /root/test20200321/

# cp  pki/private/server.key  /root/test20200321/

# cp  pki/issued/client1.domain.tld.crt  /root/test20200321/

# cp  pki/private/client1.domain.tld.key  /root/test20200321/

進入自訂資料夾
# cd   /root/test20200321/

等等需要把相關的檔案上傳到 ACM 上面, 所以上傳之前先來觀察該 Region 的 ACM 有沒有相關檔案 :) 目前是空的


將伺服器憑證和金鑰上傳到 ACM

# aws  acm  import-certificate --certificate file://server.crt --private-key file://server.key --certificate-chain  file://ca.crt --region us-east-2

{
    "CertificateArn": "arn:aws:acm:us-east-2:792117821604:certificate/2014cb32-1c3c-5412-c5d7-3b08ac91354f"
}

  • 這邊要注意的是 - 憑證和金鑰要上傳到用戶端 VPN 端點的同一區域, 我這邊以 us-east-2 為例


將用戶端憑證和金鑰上傳到 ACM

# aws  acm  import-certificate --certificate  file://client1.domain.tld.crt  --private-key file://client1.domain.tld.key --certificate-chain file://ca.crt --region us-east-2

{
    "CertificateArn": "arn:aws:acm:us-east-2:792117821604:certificate/32fc0d1d-6417-3a27-212c-7b25618a0583"
}

在該 Region 的 ACM 上面就會看到剛剛上傳的憑證





建立 用戶端 VPN 端點

接下來建立 AWS Client VPN

登入 AWS 主控台, 點選 Services -- > 點選  VPC 服務
在 VPC 主控台, 點選左方 Client VPN Endpoints


點選 Create Client VPN Endpoint

輸入名稱 / 敘述 / Client IPv4 CIDR


  • Client IPv4 CIDR 必須介於 /16 - /22 之間, 就是 Class B ~ 4 個 Class C 大小

選取 Server 憑證
勾選 Use mutual authentication -- > 選取 Client 憑證


  • 這邊可以觀察到 AWS Client VPN 有兩種驗證方式, 我們使用的是第二種
    • AD 驗證
    • 使用 Client 憑證進行交互驗證

Logging 的部分不啟用


在其他選項的部分
選取 VPC ID
DNS 的部分暫時沒有填寫, 因為要跟之後的 split-tunnel 一起進行實驗
Security Group ID 也暫時沒有選
VPN port 選取 1194 ( openVPN 預設的 port )
點選 Create Client VPN Endpoint



建立完成之後, 因為還沒有連接, 所以是 Pending-associate



將 Client VPN 與 VPC subnet 建立關聯

選取剛剛建立的 Client VPN
點選 Associations 分頁 -- > 點選 Associate

選取要關聯的 VPC 以及 Subnet
點選 Associate



經過一段時間觀察, 就會發現 Client VPN state 變成 Available



授權用戶端存取網路

選取剛剛建立的 Client VPN
點選 Authorization 分頁 -- > 點選 Authorize Ingress


Destination network to enable: 輸入 0.0.0.0/0 ( 任何 ) 
輸入 Description
點選 Add authorization rule



新增 Security Group for openVPN 連線

登入 AWS 主控台, 點選 Services -- > 點選  VPC 服務
在 VPC 主控台, 點選左方 Security Groups
點選 Create security group
輸入 名稱 / 敘述 / 選取 VPN
點選 Create

選取剛剛建立 openvpn-udp 的 security group
點選 Inbound Rules 分頁 -- > 點選 Edit rules


點選 Add Rule
選取 Custom UDP Rule
Port Range 輸入 1194
Source 填入 0.0.0.0/0
點選 Save rules 


建立完成

接下來我們要讓剛剛建立的 Client VPN 加入這筆 Security Group
點選左方的 Client VPN Endpoints

選取剛剛建立的 Client VPN
點選 Security Groups 分頁 -- > 點選 Apply Security Groups
點選剛剛建立 openvpn-udp 的 security grouip id
點選 Apply Security Groups 


  • 這邊實驗的關係, 我套用剛剛建立的 openvpn-udp 與 VPN default 規則




下載 用戶端 VPN 端點組態檔案

==== 在主機上面 ====

這邊我們就回到主機上面了, 等等可能要安裝 openVPN 的軟體以及設定

選取剛剛建立的 Client VPN
點選 Download Client Configuration


點選 Download 下載 設定檔

  • 剛剛在上面有建議可以將 container 掛載主機的特定目錄, 所以我是將設定檔放在同一個目錄 test20200321

進入特定的目錄, 以我來說, 我是將 ~/下載/test20200321 目錄與剛剛 container 共同掛載

>  cd   ~/下載/test20200321

觀察相關資訊

> ls

20200321.xml  ca.crt client1.domain.tld.crt  client1.domain.tld.key  downloaded-client-config.ovpn  server.crt  server.key

  • 這邊可以看到剛剛下載的 downloaded-client-config.ovpn 以及剛剛建立的憑證
  • 也可以看到 client 的憑證與 key


編輯 downloaded-clietn-config.ovpn

> vi  downloaded-client-config.ovpn


  • 在 remote 設定的部分, 加上任一主機名稱
    • remote test.cvpn-endpoint-002c11553b655b02c.prod.clientvpn.us-east-2.amazonaws.com 1194
  • 原因是 Client VPN 的 DNS name 是 *.cvpn-endpoint-002c11553b655b02c.prod.clientvpn.us-east-2.amazonaws.com 
    • 如果只是 cvpn-endpoint-002c11553b655b02c.prod.clientvpn.us-east-2.amazonaws.com 會解析不到

  • 在 </ca> 後面加入 cert 以及 key 兩個區段
    • cert 加入 client1.domain.tld.crt 檔案憑證內容
    • key 加入 client1.domain.tld.key 檔案 key 內容





在 openSUSE Leap 15.1 的 Network Manager 連線 openVPN

點選桌面右上角的按鈕 -- > 點選 設定值按鈕
點選左邊的網路
點選 VPN 右邊的 + 按鈕


點選 從檔案匯入 


選取剛剛的 downloaded-clietn-config.ovpn -- > 開啟

點選 加入


  • 這邊注意一下 閘道是否是 test.cvpn-endpoint-xxxxxxx

輸入管理者密碼來改變網路

由於 openVPN 是走 UDP port 1194, 所以本機的 firewall 也要開啟

#yast2  firewall

點選 左邊的 public Zone
點選 openvpn -- > 點選 Add
點選 Accept

完成 firewall 設定

連接 VPN 之前來觀察一下資訊

# ip  route  show

default via 192.168.0.1 dev wlan0 proto dhcp metric 600 
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1 linkdown 
192.168.0.0/24 dev wlan0 proto kernel scope link src 192.168.0.232 metric 600 

ping 我在 AWS 主機 172.31.14.128 -- > 失敗


接下來啟動 VPN
點選開關啟動



# ip route show

default via 10.23.0.1 dev tun0 proto static metric 50 
default via 192.168.0.1 dev wlan0 proto dhcp metric 600 
3.12.63.134 via 192.168.0.1 dev wlan0 proto static metric 600 
10.23.0.0/27 dev tun0 proto kernel scope link src 10.23.0.2 metric 50 
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1 linkdown 
192.168.0.0/24 dev wlan0 proto kernel scope link src 192.168.0.232 metric 600 
192.168.0.1 dev wlan0 proto static scope link metric 600 

ping 我在 AWS 主機 172.31.14.128 -- > 成功
ping  www.hinet.net -- > 失敗

  • 因為現在預設路由是走 VPN 出去, 我們並沒有設定 Split tunnel / DNS / 路由

另外 VPN 的設定, 個人會習慣把 自動連線取消勾選



到這邊, 如果只是要連線 AWS 的 內部 Subnet, 應該就達成了
但是如果想要
  • 可以連線 AWS Subnet
  • 也可以上網呢?

接下來就透過 Split tunnel 來達成

分割通道 ( split tunnel )
  • 啟用的時候讓 VPN 可以同時用自己的網路對外, 以及連 AWS VPC
    • 如果沒有啟用, 因為都是透過 AWS Client VPN 所以沒辦法上網

還沒有啟用 split tunnel 的時候來觀察 pint www.hinet.net 資訊

# ping www.hinet.net

PING hinet-hp.cdn.hinet.net (61.221.230.163) 56(84) bytes of data.
64 bytes from 61-221-230-163.HINET-IP.hinet.net (61.221.230.163): icmp_seq=1 ttl=50 time=196 ms
64 bytes from 61-221-230-163.HINET-IP.hinet.net (61.221.230.163): icmp_seq=2 ttl=50 time=100 ms

回到 Client VPN 設定
選取剛剛建立的 Client VPN
點選 Actions -- > Modify Client VPN Endpoint 



勾選 Enable DNS Server -- > 輸入 DNS Server IP
勾選 Enable split-tunnel
點選 Modify Client VPN Endpoint



接下來建立路由

點選 Route Table 分頁 -- > 點選 Create Route


輸入 Route destination, 這邊我給 0.0.0.0/0
選取 VPC Subnet ID
點選 Create Route


再次啟用 VPN


# ip route show

default via 10.23.0.129 dev tun0 proto static metric 50 
default via 192.168.0.1 dev wlan0 proto dhcp metric 600 
3.12.63.134 via 192.168.0.1 dev wlan0 proto static metric 600 
10.23.0.128/27 dev tun0 proto kernel scope link src 10.23.0.130 metric 50 
18.219.170.100 via 192.168.0.1 dev wlan0 proto static metric 600 
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1 linkdown 
172.31.0.0/16 via 10.23.0.129 dev tun0 proto static metric 50 
192.168.0.0/24 dev wlan0 proto kernel scope link src 192.168.0.232 metric 600 
192.168.0.1 dev wlan0 proto static scope link metric 600 

  • 這邊有觀察到 default route 有不同

ping 我在 AWS 主機 172.31.14.128 -- > 成功
ping  www.hinet.net -- > 成功

# ping www.hinet.net

PING hinet-hp.cdn.hinet.net (61.221.230.165) 56(84) bytes of data.
64 bytes from 61-221-230-165.HINET-IP.hinet.net (61.221.230.165): icmp_seq=1 ttl=33 time=610 ms
64 bytes from 61-221-230-165.HINET-IP.hinet.net (61.221.230.165): icmp_seq=2 ttl=33 time=628 ms



用 traceroute 觀察

# traceroute www.hinet.net

traceroute to www.hinet.net (61.221.230.165), 30 hops max, 60 byte packets
 1  * * *
 2  ec2-52-15-0-31.us-east-2.compute.amazonaws.com (52.15.0.31)  486.571 ms 486.564 ms ec2-52-15-0-35.us-east-2.compute.amazonaws.com (52.15.0.35)  486.501 ms
 3  100.65.26.160 (100.65.26.160)  486.391 ms 100.65.27.128 (100.65.27.128)  486.386 ms 100.65.27.32 (100.65.27.32) 486.382 ms
 4  100.66.12.60 (100.66.12.60)  486.304 ms 100.66.12.180 (100.66.12.180)  486.303 ms 100.66.12.38 (100.66.12.38) 486.214 ms
 5  100.66.15.162 (100.66.15.162)  486.330 ms 100.66.14.14 (100.66.14.14)  486.339 ms 100.66.14.134 (100.66.14.134)  486.279 ms
 6  100.66.6.229 (100.66.6.229)  486.247 ms 100.66.6.9 (100.66.6.9)  320.587 ms 100.66.7.235 (100.66.7.235)  320.967 ms

  • 這邊就可以觀察到是從 AWS 出去的


好吧, 想實驗的東西又完成一件, 離 AWS 又進了一步

~ enjoy it



Reference:

nginx 使用 SSL 憑證 with openSUSE Leap 15.1 in Azure 小記

nginx 使用 SSL 憑證 with openSUSE Leap 15.1 in Azure 小記

OS: openSUSE Leap 15.1 in Azure

今天來嘗試讓 nginx 使用 https 方式連線
要使用 https 方式連線首先要有憑證, 那就來申請憑證吧 :)

申請 SSL 憑證

我是用  https://www.sslforfree.com/ 這個網站來取得
  • 他也是利用 Let's Encrypt 來讓使用者取得憑證

輸入自己管理的網域 -- > Create Free SSL Certificate


選取驗證的方式, 我是使用 DNS 的方式, 點選 Manual Verification(DNS)


DNS 驗證的方式就是藉由新增 TXT 記錄來進行驗證 
-- > 點選 Manually Verify Domain

我 DNS 代管是使用 Gandi.net

按照上面的要求在 DNS 代管的網站新增兩筆 TXT Record


  • 如果要確認是否設定完成, 可以使用 host 指令
    • #host  -t txt  _acme-challenge.YOUR_DOMAIN

DNS 紀錄設定好之後

可以點選 Verify 的兩個連結觀察
  • Gandi 最小 TTL 值是 300 秒, 雖然他要求 1 秒的 TTL, 不過只要等 300 秒, 還是可以檢查 Value, 所以不影響

點選 Download SSL Certificate


如果剛剛的 DNS TXT 紀錄都有設定正確
就會出現 Certificate Successfully Generated 頁面
上面是說 SSL 憑證 90 天之後過期, 可以註冊帳號集中管理或是提醒到期, 這個部分就看個人

畫面中央有 Certificate Files
有相關檔案, 點選 Download All SSL Certificate Files 來下載 SSL 憑證檔案

這個時候會下載一個 sslforfree.zip 的檔案, 裡面包含 3 個檔案
  • ca_bundle.crt - 中繼憑證
  • certificate.crt - 公鑰
  • private.key - 私鑰

SSL 憑證格式的資訊如果想要進一步了解, 可以參考保哥的文章

接下來可以參考網站提供的安裝文件 https://www.sslforfree.com/#tutorials


這邊就根據自己的平臺以及伺服器來選擇

我使用 nginx
為了管理方便我在 /etc/nginx 目錄下建立一個 ssl  目錄

# mkdir  /etc/nginx/ssl

將上面的 3 個檔案上傳到 伺服器上面 /etc/nginx/ssl 目錄下
  • ca_bundle.crt - 中繼憑證
  • certificate.crt - 公鑰
  • private.key - 私鑰

將 公鑰與中繼憑證合併

# cat   /etc/nginx/ssl/certificate.crt  > /etc/nginx/ssl/your_domain.crt
# printf  "\n"  >>  /etc/nginx/ssl/your_domain.crt 
# cat   /etc/nginx/ssl/ca_bundle.crt  >>  /etc/nginx/ssl/your_domain.crt

  • 這邊注意第一個指令是用 > 輸出導向, 然後後面是用 >>  附加的方式
  • certificate.crt 以及 ca_bundle.crt 順序要注意 

修改 nginx 設定檔
# vim  /etc/nginx/nginx.conf

worker_processes  1;
events {
    worker_connections  1024;
    use epoll;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
    include conf.d/*.conf;
    server {
        listen       80;
        listen       443 ssl;
        server_name  YOUR_DOMAIN;
        ssl_certificate      /etc/nginx/ssl/your_domin.crt;
        ssl_certificate_key  /etc/nginx/ssl/private.key;
        location / {
            root   /srv/www/htdocs/;
            index  index.html index.htm;
        }
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   /srv/www/htdocs/;
        }
    }
    
    include vhosts.d/*.conf;
}

  • 加入上面紅色部分

將 nginx 服務 reload

# systemctl   reload   nginx

因為是走 HTTPS, 所以記得要開 port 443 

在 Azure 該 VM 的網路設定內, 點選 新增輸入連接埠規則,設定 port 443 可以連線

開啟瀏覽器, 輸入 https://YOUR_DOMAIN
就可以看到可愛的鎖頭符號了


又往 nginx 前進一步了 :)

~ enjoy it


Reference:

Saturday

7 March, 2020

使用 curl 測試 CDN 小記

使用 curl 測試 CDN 小記

OS: openSUSE Leap 15.1
Curl: 7.60.0

因為公司也有 CDN 的服務, 所以就來 study 一下如何測試 CDN

找了網路上的文章來進行實驗

> curl  -I  img1.momoshop.com.tw

HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 206
Connection: keep-alive
Date: Thu, 13 Feb 2020 06:37:14 GMT
Last-Modified: Wed, 04 Sep 2019 08:33:23 GMT
ETag: "5d6f76d3-ce"
Expires: Fri, 12 Feb 2021 06:37:14 GMT
Cache-Control: max-age=31536000
X-Image-Server: a1-imgweb62
X-Cache-Server: a1-rproxy64
X-Cache-Status: HIT
Cache-Control: public
Accept-Ranges: bytes
X-Cache: Hit from cloudfront
Via: 1.1 ff0896bca963fdb839934a38daad05c9.cloudfront.net (CloudFront)
X-Amz-Cf-Pop: TPE50-C1
X-Amz-Cf-Id: s_DGUUBq7VKqDZprbRdA75kJeG5So0PLUwMRyWjqwA4TxjSefOmfEg==
Age: 1923399


  • -I, --head (HTTP  FTP FILE) Fetch the  headers only! 顯示 Headers
  • Cache-Control:
  • X-Cache: 是否在 CDN 有快取
    • HIT: 在 CDN 上有快取
    • MISS: 在 CDN 上面沒有快取, 會跟原站抓
  • X-Amz-Cf-Pop: 這個欄位是快取的站, 這邊可以觀察是 Taipei 的 Pop 點
    • 但是不同的供應商, 會有不同的欄位, Cloudflare 可能就是 CF-RAY: 56fc8a38f94545d0-TPE
  • ETag:

  • Expires: 過期時間
    • 瀏覽器收到這個 Response 之後就會把這個資源給快取起來,當下一次使用者再度造訪這個頁面或是要求這個圖片的資源的時候,瀏覽器會檢視「現在的時間」是否有超過這個 Expires。如果沒有超過的話,那瀏覽器「不會發送任何 Request」,而是直接從電腦裡面已經存好的 Cache 拿資料。

  • RFC2616 規範 max-age 會蓋掉 Expires, 所以實際上用到的是 Cache-Control: max-age



剛剛是針對某個網站
哪如果是針對 CDN 可能快取的物件呢? 

> curl -I  https://img1.momoshop.com.tw/goodsimg/0006/750/353/6750353_L.jpg?t=1581517754

HTTP/2 200 
content-type: image/jpeg
content-length: 22654
date: Fri, 06 Mar 2020 13:40:47 GMT
last-modified: Wed, 28 Aug 2019 15:00:03 GMT
etag: "5d6696f3-587e"
expires: Sat, 06 Mar 2021 13:40:47 GMT
cache-control: max-age=31536000
x-image-server: b1-imgweb61
access-control-allow-origin: *
access-control-max-age: 1000
access-control-allow-methods: POST, GET, OPTIONS, DELETE, PUT
access-control-allow-headers: x-requested-with, Content-Type, origin, authorization, accept, client-security-token
x-cache-server: a1-rproxy65
x-cache-status: HIT
cache-control: public
accept-ranges: bytes
x-cache: Miss from cloudfront
via: 1.1 5c4e99b05f9fd6102a3e039a6bd98968.cloudfront.net (CloudFront)
x-amz-cf-pop: TPE50-C1
x-amz-cf-id: JrqvYZNlLjV5zHS323SyuQ8pqzJgciSDOW4sEl1kl1Wj6ky_D4jWjg==

上面有提到過的就不重提
  • X-cache: Miss from cloudfront ( Cloudfront 上面沒有快取 ), 所以 CDN 會跟原站抓
    • 這邊也可以觀察到沒有 age 的 header, 也就是說沒有物件在 CDN 上已經快取的時間
  • 也可以去觀察 x-cache-server 以及 x-image-server 資訊
  • last-modified:
    • 會跟 If-Modified-Since 搭配使用, 如果超過時間但是沒有變動, 還是會從快取出

很短的時間重新抓一次

> curl -I https://img1.momoshop.com.tw/goodsimg/0006/750/353/6750353_L.jpg?t=1581517754

HTTP/2 200 
content-type: image/jpeg
content-length: 22654
date: Fri, 06 Mar 2020 13:40:47 GMT
last-modified: Wed, 28 Aug 2019 15:00:03 GMT
etag: "5d6696f3-587e"
expires: Sat, 06 Mar 2021 13:40:47 GMT
cache-control: max-age=31536000
x-image-server: b1-imgweb61
access-control-allow-origin: *
access-control-max-age: 1000
access-control-allow-methods: POST, GET, OPTIONS, DELETE, PUT
access-control-allow-headers: x-requested-with, Content-Type, origin, authorization, accept, client-security-token
x-cache-server: a1-rproxy65
x-cache-status: HIT
cache-control: public
accept-ranges: bytes
x-cache: Hit from cloudfront
via: 1.1 41d05f95698dc73a0a8a2f90b9eb739a.cloudfront.net (CloudFront)
x-amz-cf-pop: TPE50-C1
x-amz-cf-id: YL_Ii4eNQTB0VfTIlpSo77A8cHB4aOk7Mv_K4dhix_OqBhbW6tkqHw==
age: 28

  • 這邊可以觀察到 CloudFront 已經有資料, 然後也有 age 的資料

接下來進行另外一個測試 就是 支援 TLS 的版本
現在 TLS 版本的支援, 很多瀏覽器都會要求到一定的 TLS 版本, 目前 大概都要支援到 TLS 1.2 以上的版本

> curl  -I  -v  --tlsv1.0  https://img1.momoshop.com.tw

* Rebuilt URL to: https://img1.momoshop.com.tw/
*   Trying 13.35.153.7...
* TCP_NODELAY set
* Connected to img1.momoshop.com.tw (13.35.153.7) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* TLSv1.0 (OUT), TLS handshake, Client hello (1):
* TLSv1.0 (IN), TLS alert, Server hello (2):
* error:1409442E:SSL routines:ssl3_read_bytes:tlsv1 alert protocol version
* stopped the pause stream!
* Closing connection 0
curl: (35) error:1409442E:SSL routines:ssl3_read_bytes:tlsv1 alert protocol version

  • 這邊使用 -v 來顯示詳細資訊
  • --tlsv1.0 指定使用 TLS 1.0 協定
  • 這邊可以觀察到 使用 TLS 1.0 是被拒絕的

接下來嘗試 TLS 1.1 and TLS 1.2

> curl  -I  -v --tlsv1.1  https://img1.momoshop.com.tw

* Rebuilt URL to: https://img1.momoshop.com.tw/
*   Trying 13.35.153.65...
* TCP_NODELAY set
* Connected to img1.momoshop.com.tw (13.35.153.65) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* TLSv1.1 (OUT), TLS handshake, Client hello (1):
* TLSv1.1 (IN), TLS handshake, Server hello (2):
* TLSv1.1 (IN), TLS handshake, Certificate (11):
* TLSv1.1 (IN), TLS handshake, Server key exchange (12):
* TLSv1.1 (IN), TLS handshake, Server finished (14):
* TLSv1.1 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.1 (OUT), TLS change cipher, Client hello (1):
* TLSv1.1 (OUT), TLS handshake, Finished (20):
* TLSv1.1 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.1 / ECDHE-RSA-AES128-SHA
* ALPN, server accepted to use h2
* Server certificate:
*  subject: CN=*.momoshop.com.tw
*  start date: Jun  3 00:00:00 2019 GMT
*  expire date: Jul  3 12:00:00 2020 GMT
*  subjectAltName: host "img1.momoshop.com.tw" matched cert's "*.momoshop.com.tw"
*  issuer: C=US; O=Amazon; OU=Server CA 1B; CN=Amazon
*  SSL certificate verify ok.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x564c5fcb9040)
> HEAD / HTTP/2
> Host: img1.momoshop.com.tw
> User-Agent: curl/7.60.0
> Accept: */*
* Connection state changed (MAX_CONCURRENT_STREAMS == 128)!
< HTTP/2 200 
HTTP/2 200 

> curl -I -v --tlsv1.2 https://img1.momoshop.com.tw

* Rebuilt URL to: https://img1.momoshop.com.tw/
*   Trying 13.35.153.7...
* TCP_NODELAY set
* Connected to img1.momoshop.com.tw (13.35.153.7) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Client hello (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
* ALPN, server accepted to use h2
* Server certificate:
*  subject: CN=*.momoshop.com.tw
*  start date: Jun  3 00:00:00 2019 GMT
*  expire date: Jul  3 12:00:00 2020 GMT
*  subjectAltName: host "img1.momoshop.com.tw" matched cert's "*.momoshop.com.tw"
*  issuer: C=US; O=Amazon; OU=Server CA 1B; CN=Amazon
*  SSL certificate verify ok.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x56535129a040)
> HEAD / HTTP/2
> Host: img1.momoshop.com.tw
> User-Agent: curl/7.60.0
> Accept: */*
* Connection state changed (MAX_CONCURRENT_STREAMS == 128)!
< HTTP/2 200 
HTTP/2 200 

  • 其實如果沒有特別指定, 會用比較高的版本去連接
  • 這邊可以觀察 TLS 1.1 and TLS 1.2 都支援

同場加映:
然後也可以用另外一個指令來檢查 TLS, 就是 sslscan 指令

> sslscan  https://img1.momoshop.com.tw

Version: 1.11.10
OpenSSL 1.0.2p-fips  14 Aug 2018

OpenSSL version does not support SSLv2
SSLv2 ciphers will not be detected

OpenSSL version does not support SSLv3
SSLv3 ciphers will not be detected
Testing SSL server img1.momoshop.com.tw on port 443 using SNI name img1.momoshop.com.tw

  TLS Fallback SCSV:
Server does not support TLS Fallback SCSV

  TLS renegotiation:
Session renegotiation not supported

  TLS Compression:
Compression disabled

  Heartbleed:
TLS 1.2 not vulnerable to heartbleed
TLS 1.1 not vulnerable to heartbleed
TLS 1.0 not vulnerable to heartbleed

  Supported Server Cipher(s):
Preferred TLSv1.2  128 bits ECDHE-RSA-AES128-GCM-SHA256   Curve P-256 DHE 256
Accepted  TLSv1.2 128 bits  ECDHE-RSA-AES128-SHA256       Curve P-256 DHE 256
Accepted  TLSv1.2 128 bits  ECDHE-RSA-AES128-SHA          Curve P-256 DHE 256
Accepted  TLSv1.2 256 bits  ECDHE-RSA-AES256-GCM-SHA384   Curve P-256 DHE 256
Accepted  TLSv1.2 256 bits  ECDHE-RSA-AES256-SHA384       Curve P-256 DHE 256
Accepted  TLSv1.2 256 bits  ECDHE-RSA-AES256-SHA          Curve P-256 DHE 256
Accepted  TLSv1.2 128 bits  AES128-GCM-SHA256            
Accepted  TLSv1.2 256 bits  AES256-GCM-SHA384            
Accepted  TLSv1.2 128 bits  AES128-SHA256                
Accepted  TLSv1.2 256 bits  AES256-SHA                   
Accepted  TLSv1.2 128 bits  AES128-SHA                   
Preferred TLSv1.1  128 bits ECDHE-RSA-AES128-SHA          Curve P-256 DHE 256
Accepted  TLSv1.1 256 bits  ECDHE-RSA-AES256-SHA          Curve P-256 DHE 256
Accepted  TLSv1.1 256 bits  AES256-SHA                   
Accepted  TLSv1.1 128 bits  AES128-SHA                   

  SSL Certificate:
Signature Algorithm: sha256WithRSAEncryption
RSA Key Strength:    2048

Subject:  *.momoshop.com.tw
Altnames: DNS:*.momoshop.com.tw
Issuer:   Amazon

Not valid before: Jun  3 00:00:00 2019 GMT
Not valid after:  Jul 3 12:00:00 2020 GMT

然後也常常看到網路上的人使用下列的選項
> curl  -ksvo  /dev/null  https://img1.momoshop.com.tw

  • -k, --insecure
  • -s, --silent, Silent or quiet mode. Don't show progress meter or error messages.
  • -v, --verbose
  •  -o, --output <file>

整理一下今天學習到的知識重點

也許可以利用 curl -I 的方式來看 Header 來觀察是否有 CDN, 也許 Header 不一樣

> curl -I  https://media.etmall.com.tw

HTTP/2 403 
server: HiNetCDN/1908
date: Sat, 07 Mar 2020 15:00:16 GMT
content-type: text/html
content-length: 1147
vary: Accept-Encoding
x-cache: MISS, MISS, MISS
x-request-id: 08a83a10d0e14edecab443f4bde4c753

> curl  -I  http://cf.shopee.tw

HTTP/1.1 404 Not Found
Server: NWS_Oversea_AP
Connection: keep-alive
Date: Sat, 07 Mar 2020 15:00:36 GMT
Last-Modified: Sat, 07 Mar 2020 15:00:00 GMT
Content-Type: text/plain; charset=utf-8
Content-Length: 19
X-Content-Type-Options: nosniff
X-Daa-Tunnel: hop_count=2
X-NWS-LOG-UUID: 5423788696303268195 b38e6f5a9afc4fde3c81e984a88d9c0f
Access-Control-Allow-Origin: *
X-CDN: tencent
X-Cache-Lookup: Hit From Upstream

可以藉由觀察 Cache-Control 來觀察是否快取
  • public
    • 可以由任何快取給存取
  • private
    • 快取只給一個使用者使用,且不能被共用的快取伺服器給儲存過。隱私視窗(無痕模式)的快取就可能是這樣子。
  • no-cache
    • 快取伺服器在把已儲存的複製版本傳給請求者之前,先會送一個請求給網頁伺服器做驗證
  • no-store
    • 快取不該存取任何的使用者請求或者伺服器的回覆。每個請求都是送到原始的伺服器去取得資源。

期限的部分一般則是可以看 Cache-Control 的 max-age 來決定
會使用 etag 或是 last-modified 來進行快取內容驗證

再度前進一小步 :)

~ enjoy it


Reference:


nginx with openSUSE Leap 15.1 in Azure 小記 Part 2

nginx with openSUSE Leap 15.1 in Azure 小記 Part 2

OS: openSUSE Leap 15.1 in Azure
Nginx: 1.14.2

上次練習 nginx 靜態網頁以及 proxy, 今天來實驗 HTTP Load Balancing

架構想法如下


實驗環境
OS: openSUSE Leap 15.1 in Azure x 3 VM
  • 前面有 1 台 openSUSE Leap 15.1 執行 nginx 
  • 後面有 2 台 openSUSE Leap 15.1 使用 container 執行 Web 服務

參考上次的文章

首先建立 2 台 openSUSE Leap 15.1 in Azure, 執行以下動作
  • 啟動 docker 服務
    • # systemctl  start docker
  • 執行 container 然後 port 開在 80
    • # docker  run -d -p  80:80 russmckendrick/cluster
  • Azure 該 VM 的網路設定內, 設定 port 80 可以連線
  • 設定該 VM DNS 名稱
  • 確認都可以進行存取





建立 1 台 openSUSE Leap 15.1 in Azure, 執行以下動作
  • 使用 zypper 指令 安裝 nginx
    • # zypper  install  nginx
  • 啟動 nginx 服務
    • # systemctl start nginx
    • # systemctl  enable  nginx
  • 設定 DNS 名稱

上面的動作前一篇文章就已經有了, 所以不贅述

接下來進行 HTTP Load Balancing 實驗

修改 nginx 設定檔

# vi   /etc/nginx/nginx.conf

worker_processes  1;
events {
    worker_connections  1024;
    use epoll;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
    include conf.d/*.conf;
    upstream backend {
            server test2020022801.eastus.cloudapp.azure.com;
            server test2020022802.eastus.cloudapp.azure.com;
    }
    server {
        listen       80;
        server_name  localhost;
        location / {
            root   /srv/www/htdocs/;
            index  index.html index.htm;
            proxy_pass http://backend;
        }
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   /srv/www/htdocs/;
        }
    }
    
    include vhosts.d/*.conf;
}

  • 新增 upstream backend 區段, 指向剛剛建立的 2 台 Web 服務
  • 新增 proxy_pass 指向 http://backend

善用 #nginx -t 檢查語法
  • 一開始是寫獨立的 http 區段, 結果就被警告 http 重複設定

將服務 reload 

# systemctl  reload  nginx

進行測試
在瀏覽器開啟 http://testnginx.eastus.cloudapp.azure.com


  • 確認會導向後端不同的 Web 服務

Load Balancing 的方式有 6 種
  • Nginx open source 支援其中4種, nginx plus 支援 6 種
    • Round Robin ( 預設 )
    • Least Connections
    • IP Hash
    • Generic Hash
    • Least Time ( NGINX Plus only )
    • Random

接下來多實驗一個設定 Server Weight

剛剛有提到, 預設使用 Round Robin 方式將連線平均的分配到後端的服務
那如果 VM 他的規格大小不一樣, 或是想要測試金絲雀佈署這樣的改版測試呢?

這個時候考慮使用 Server Weight 權重方式來因應

修改 nginx 設定檔

# vi   /etc/nginx/nginx.conf

worker_processes  1;
events {
    worker_connections  1024;
    use epoll;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
    include conf.d/*.conf;
    upstream backend {
           server test2020022801.eastus.cloudapp.azure.com weight=3;
           server test2020022802.eastus.cloudapp.azure.com;
    }
    server {
        listen       80;
        server_name  localhost;
        location / {
            root   /srv/www/htdocs/;
            index  index.html index.htm;
            proxy_pass http://backend;
        }
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   /srv/www/htdocs/;
        }
    }
    
    include vhosts.d/*.conf;
}

  • 針對剛剛後端服務其中一台設定 weight=3
    • 沒有設定的話, 權重設定預設是 1, 目前有 2 台機器服務, 所以總共是 3 + 1 = 4, 也就是說 test2020022801 被存取的次數就會佔 3/4 ( 75% ), 另外一台是 1/4 ( 25% )

將服務 reload 

# systemctl  reload  nginx

進行測試
在瀏覽器開啟 http://testnginx.eastus.cloudapp.azure.com

  • 觀察 2 台機器服務的顯示比例

這樣算是朝向 nginx 的一小步  :)

~ enjoy it


Reference

Sunday

23 February, 2020

nginx with openSUSE Leap 15.1 in Azure 小記

nginx with openSUSE Leap 15.1 in Azure 小記


OS: openSUSE Leap 15.1 in Azure
Nginx: 1.14.2


之前 web 服務都是使用 Apache 比較多, 但是最近覺得要會 nginx 才能符合之後的需求, 所以開始來練習 nginx :) 今天主要練習
  • Nginx 作爲靜態網頁
  • Nginx 作為 Proxy Server


Nginx


使用環境 openSUSE Leap 15.1 in Azure
  • 已經登入到 Azure Portal 並建立一台 openSUSE Leap 15.1
  • 使用 ssh 連線在 Azure 上面的 openSUSE Leap 15.1


先來使用 zypper 指令 安裝 nginx 


# zypper  install  nginx


Loading repository data...
Reading installed packages...
Resolving package dependencies...


The following 9 NEW packages are going to be installed:
  libXpm4 libgd3 libjbig2 libjpeg8 libtiff5 libwebp6 libxslt1 nginx vim-plugin-nginx


The following recommended package was automatically selected:
  vim-plugin-nginx


9 new packages to install.
Overall download size: 1.7 MiB. Already cached: 0 B. After the operation, additional 4.8 MiB will be used.
Continue? [y/n/v/...? shows all options] (y):  Y


觀察服務狀態


# systemctl status nginx


● nginx.service - The nginx HTTP and reverse proxy server
   Loaded: loaded (/usr/lib/systemd/system/nginx.service; disabled; vendor preset: disabled)
   Active: inactive (dead)


啟動 nginx 服務


# systemctl start nginx


觀察相關資訊


# systemctl status nginx


● nginx.service - The nginx HTTP and reverse proxy server
   Loaded: loaded (/usr/lib/systemd/system/nginx.service; disabled; vendor preset: disabled)
   Active: active (running) since Thu 2020-02-20 13:00:00 UTC; 1s ago


確認開機是否會自動啟動


# systemctl  is-enabled  nginx
disabled


設定開啟自動啟動


# systemctl  enable  nginx


Created symlink /etc/systemd/system/multi-user.target.wants/nginx.service → /usr/lib/systemd/system/nginx.service.


再次觀察
# systemctl  is-enabled  nginx
enabled


這樣 nginx 就已啟動然後開機後也會自動啟動


Lab 1: 測試靜態網頁


觀察 listen port
  • 早期是用 netstat 指令, 現在是用 ss 指令了


# ss  -tupln


Netid State      Recv-Q Send-Q                                 Local Address:Port                     Peer Address:Port              
udp   UNCONN     0 0                                         0.0.0.0%eth0:68                       0.0.0.0:* users:(("wickedd-dhcp4",pid=685,fd=9))
tcp   LISTEN     0 128                                             0.0.0.0:80             0.0.0.0:* users:(("nginx",pid=120751,fd=6),("nginx",pid=120750,fd=6))
tcp   LISTEN     0 128                                             0.0.0.0:22             0.0.0.0:* users:(("sshd",pid=1189,fd=3))
tcp   LISTEN     0 128                                                 [::]:22           [::]:* users:(("sshd",pid=1189,fd=4))


有觀察到 port 80 listen, 但是這個是本機的狀況, 要可以對外連線, 還要在 Azure 上面設定 Security Group 讓 網路流量可以通過


在 Azure 該 VM 的網路設定內, 點選 新增輸入連接埠規則,設定 port 80 可以連線




接下來測試網頁狀況


在瀏覽器開啟 http://YOUR_SERVER_IP


  • 這個時候會得到 403 Forbidden, 


觀察 error.log
# cat  /var/log/nginx/error.log


2020/02/20 13:01:32 [error] 120751#120751: *1 directory index of "/srv/www/htdocs/" is forbidden,


藉由 nginx -t 來觀察設定檔位置以及有沒有問題


# nginx  -t


nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful


  • 從這邊可以得知設定檔在 /etc/nginx/nginx.conf


觀察一下目前的設定檔


# egrep  -v  '^$|^#|#'  /etc/nginx/nginx.conf 


worker_processes  1;
events {
    worker_connections  1024;
    use epoll;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
    include conf.d/*.conf;
    server {
        listen       80;
        server_name  localhost;
        location / {
            root   /srv/www/htdocs/;
            index  index.html index.htm;
        }
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   /srv/www/htdocs/;
        }
    }
    
    include vhosts.d/*.conf;
}


整理一下
  • 網站的根目錄應該是在 /srv/www/htdocs
  • 首頁的檔案應該是 index.html 或是 index.htm
  • 觀察  /etc/nginx/conf.d/ 目錄下     - 沒有檔案
  • 觀察  /etc/nginx/vhosts.d/ 目錄下 - 沒有檔案


觀察一下資訊
# ls  /srv/www/htdocs/
50x.html


該目錄中, 並沒有 index.html 或是 index.htm,  所以就會 Forbidden


嘗試建立 /srv/www/htdocs/index.html
# vim  /srv/www/htdocs/index.html


<html> This is lab site </html>


測試是否生效
在瀏覽器開啟 http://YOUR_SERVER_IP




到這邊的話, 基本的靜態網頁測試就應該可以了

Lab 2:  測試 Proxy Server 的用法


為了要有測試的感覺, 先把 docker 服務啟動


# systemctl  start  docker


觀察服務狀態


# systemctl  status  docker


● docker.service - Docker Application Container Engine
   Loaded: loaded (/usr/lib/systemd/system/docker.service; disabled; vendor pre>
   Active: active (running) since Sat 2020-02-22 04:12:17 UTC; 5min ago


執行 container 然後 port 開在 8080 
# docker  run  -d  -p  8080:80  russmckendrick/cluster


在 Azure 該 VM 的網路設定內, 設定 port 8080 可以連線






測試是否生效
在瀏覽器開啟 http://YOUR_SERVER_IP:8080




應該會看到網頁以及該 container 的 id


從這邊我們可以觀察到這個服務是正常的


接下來要進行 Proxy Server 的測試
測試想法
  • 當使用者連線到某個網域名稱( FQDN ), 就會轉到 本機 port 8080


將剛剛 Azure 上面的安全性規則, 允許 port 8080 刪除




再次嘗試存取剛剛的網站 觀察相關資訊
在瀏覽器開啟 http://YOUR_SERVER_IP:8080


這個時候其實會發現無法存取 ( 因為安全性規則 firewall 已經被刪除)


開始進行實作
在 Azure 上面替 openSUSE Leap 15.1 設定 DNS 名稱


在 VM 的概觀頁面上面可以看到有 DNS 設定的按鈕
點選 設定
  • 這個動作其實是會進入該公用 IP 的組態內




輸入 DNS 名稱




點選儲存
這個時候這個 VM 就會將這個名稱綁定公用 IP


修改 nginx 設定檔


# vim   /etc/nginx/nginx.conf


worker_processes  1;
events {
    worker_connections  1024;
    use epoll;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
    include conf.d/*.conf;
    server {
       server_name test20200222.eastus.cloudapp.azure.com;
       location / {
       proxy_pass http://127.0.0.1:8080;
       }
    }
    server {
        listen       80;
        server_name  localhost;
        location / {
            root   /srv/www/htdocs/;
            index  index.html index.htm;
        }
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   /srv/www/htdocs/;
        }
    }
    
    include vhosts.d/*.conf;
}


  • 在  http 區段內新增一個 server 區段
  • server_name 指定剛剛綁定的 FQDN
  • Proxy_pass 指向 port 8080


這邊要善用  nginx -t 來檢查相關設定


進行測試
在瀏覽器開啟 http://test20200222.eastus.cloudapp.azure.com
這個時候會看到剛剛啟動的網頁
Proxy Server 功能測試完畢


整理資訊
  • 設定檔 /etc/nginx/nginx.conf
    • 相關目錄 /etc/nginx
  • Log 目錄 : /var/log/nginx


這樣算是朝向 nginx 的一小步  :)


~ enjoy it


Reference

Saturday

11 January, 2020

使用 Google Stackdriver Monitoring API Python Samples 監控 過去一週 CPU 小於 20% VM小記

20191229

使用 Google Stackdriver Monitoring API Python Samples 監控 過去一週 CPU 小於 20% VM小記

OS: container with openSUSE Leap 15.1

今天要來嘗試使用 Stackdriver monitor API 透過 python 列出過去一週 CPU 小於 20 % 的 VM

環境使用之前建立好的 openSUSE Leap 15.1, 上面已經安裝好雲端的工具

==== 在主機上面 ====

啟動 container

> docker  run  -v  ~/.aws:/root/.aws -v  ~/.azure:/root/.azure  -v ~/.config/gcloud:/root/.config/gcloud  -v  ~/.ssh:/root/.ssh  -it  sakana/ansible_opensuse151  /bin/bash

==== 在 container 內 ====

在這邊使用服務帳戶的方式來處理, 所以要先建立服務帳戶

建立的方式有 2 種

==== 1. GCP Console 方式 ====

登入 GCP console

點選 導覽選單 -- > IAM 與管理 -- > 服務帳戶 

點選 建立服務帳戶


輸入帳戶名稱 -- > 建立

角色的部分選取 監控/Monitoring 管理員  -- > 繼續


點選 建立金鑰

選取金鑰類型, 這邊我選 JSON  -- > 建立


下載金鑰到本機

點選 完成
完成服務帳號建立以及金鑰建立

==== 2. 指令方式 ====

參考官方網頁

建立服務帳戶

# gcloud iam service-accounts create test20200111 --project  YOUR_PROJECT_ID

  • test20200111 是服務帳戶名稱
  • YOUR_PROJECT_ID 請換成自己的 project id

向服務帳戶授予權限

用您的專案 ID 取代 [PROJECT_ID]
#gcloud  projects  add-iam-policy-binding [PROJECT_ID] --member "serviceAccount:[NAME]@[PROJECT_ID].iam.gserviceaccount.com" --role "roles/monitoring.admin"

  • 所以這邊可以觀察到 監控管理員的權限是綁定在 project
  • roles/monitoring.admin 是觀察來的, 可以透過 #gcloud  projects  get-iam-policy [PROJECT_ID] 來看相關的權限

另外網路上也有看到找出服務帳戶 Role 的過濾方式

# gcloud projects get-iam-policy [PROJECT_ID] --flatten="bindings[].members" --filter="bindings.members:[NAME]@[PROJECT_ID].iam.gserviceaccount.com"

---
bindings:
  members: serviceAccount:sakanatest-20200111-monitor@xxxxxxx.iam.gserviceaccount.com
  role: roles/monitoring.admin
etag: BwWb1FtLJ4s=
version: 1

產生金鑰檔案

用金鑰檔案的名稱取代 [FILE_NAME]
#gcloud  iam  service-accounts  keys  create  [FILE_NAME].json --iam-account [NAME]@[PROJECT_ID].iam.gserviceaccount.com

created key [5abac9d47cd2g96386a05bad735d241d59a00897] of type [json] as [/root/test20200111.json] for [test20200111@xxxxxxxxx.iam.gserviceaccount.com]

  • 用指令的好處是可以直接指定憑證的位置, 我在下指令的時候是用 /root/test20200111.json

=================================

服務帳戶與金鑰準備好了之後, 接下來就是取得範例程式


更動的部分如下 ( 使用 diff 指令, 左邊是改寫, 右邊是 google 原來的範例 )

> diff snippets.py snippets-orig.py 

14,18d13
< # 
< # Edit by Max 2020/1/11
< # 因應工作需求, 改寫 snippets.py
< # File from https://github.com/GoogleCloudPlatform/python-docs-samples/tree/master/monitoring/api/v3/cloud-client
119,130d113
< # 改寫 list_time_series_aggregate
< # 
< # 這邊定義要查詢的區間
< query_time = input("Please input your query time in seconds, for example, 7 Days is 604800:  ") or 604800
< query_time_int=int(query_time) # 這邊將 query_time type 從 str 轉型為 int
< print("")
< cpu_threshold = input("Please input cpu usage under threshold, like 0.2 for 20%:  ") or 0.2
< cpu_threshold_float = float(cpu_threshold)
< print("")
140c123
<     interval.start_time.seconds = int(now - query_time_int) # 這邊用 query_time 來彈性調整
---
>     interval.start_time.seconds = int(now - 3600)
143c126
<     aggregation.alignment_period.seconds = query_time_int  # 這邊用 query_time 來彈性調整
---
>     aggregation.alignment_period.seconds = 1200  # 20 minutes
154,160c137
<       cpuUtil = result.points[0].value.double_value
<       if cpuUtil < cpu_threshold_float: #需要判斷的 CPU threshold, 用 cpu_threshold 來彈性調整
<           print("instance name:", result.metric.labels) # 列出 instance 名稱
<           # instance_id 是放在 resource.labels 下, 以字典的方式儲存, 所以透過 ['KEY_NAME'] 取出
<           print("instance id:", result.resource.labels['instance_id']) # 列出 instance id 來區別同樣名稱的 VM
<           print("CPU utilization:", cpuUtil *100, "% \n") # 列出 cpu 使用量
<     # print(result) 註解原來的方式
---
>         print(result)

接下來設定應用程式驗證作業需要的環境變數

定義 project , 請帶入自己 project ID
# export  GOOGLE_CLOUD_PROJECT=[PROJECT_ID]

定義剛剛的 json 檔案的路徑, 例如 /root/test20200111.json
# export GOOGLE_APPLICATION_CREDENTIALS="[path/key-name.json]"


確認有定義完成

# echo  $GOOGLE_CLOUD_PROJECT
# echo  $GOOGLE_APPLICATION_CREDENTIALS

使用 pip 安裝 python 相依性的套件
# pip  install  -r  requirements.txt

執行剛剛下載修改的 snippet.py

# python3  snippets.py  list-time-series-aggregate

Please input your query time in seconds, for example, 7 Days is 604800:  604800

Please input cpu usage under threshold, like 0.2 for 20%:  0.3

instance name: {'instance_name': 'test'}
instance id: 3255911329394624968
CPU utilization: 17.11500122 % 

instance name: {'instance_name': 'test2'}
instance id: 3713200083697575388
CPU utilization: 0.6797669215641027 % 

instance name: {'instance_name': 'test'}
instance id: 8590409858061083796
CPU utilization: 0.6412688036029409 % 

  • 這邊我改成互動的方式, 輸入要查詢的區間, 使用秒數爲單位
  • 輸入CPU 使用量的門檻值, 如果要列出 20% 以下就輸入 0.2

這樣就可以列出過去一週 CPU 小於 20 % 的 VM :)

另外補充, 當服務帳戶刪除的時候, 剛 members 與 Roles 還是在 project 上面, 所以要記得移除權限

例如
# gcloud projects remove-iam-policy-binding [PROJECT_ID] --member=serviceAccount:[NAME]@[PROJECT_ID].iam.gserviceaccount.com --role=roles/monitoring.admin

這樣又朝向 GCP 邁進一步

~ enjoy  it

Reference